From 15318cad33835e4e2dc620d033e43cd930676cdd Mon Sep 17 00:00:00 2001 From: kergoth Date: Fri, 25 Jan 2002 22:14:26 +0000 Subject: Initial revision --- (limited to 'core') diff --git a/core/.cvsignore b/core/.cvsignore new file mode 100644 index 0000000..e3d8c4b --- a/dev/null +++ b/core/.cvsignore @@ -0,0 +1,13 @@ +moc_* +*.moc +Makefile +appearancesettingsbase.h +soundsettingsbase.h +lightsettingsbase.h +languagesettingsbase.cpp +rotationsettingsbase.cpp +appearancesettingsbase.cpp +lightsettingsbase.cpp +languagesettingsbase.h +rotationsettingsbase.h +soundsettingsbase.cpp diff --git a/core/applets/batteryapplet/.cvsignore b/core/applets/batteryapplet/.cvsignore new file mode 100644 index 0000000..edfa921 --- a/dev/null +++ b/core/applets/batteryapplet/.cvsignore @@ -0,0 +1,3 @@ +moc_* +*.moc +Makefile diff --git a/core/applets/batteryapplet/Makefile.in b/core/applets/batteryapplet/Makefile.in new file mode 100644 index 0000000..0493fd6 --- a/dev/null +++ b/core/applets/batteryapplet/Makefile.in @@ -0,0 +1,122 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../../plugins/applets/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = batteryapplet +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = battery.h \ + batterystatus.h \ + batteryappletimpl.h +SOURCES = battery.cpp \ + batterystatus.cpp \ + batteryappletimpl.cpp +OBJECTS = battery.o \ + batterystatus.o \ + batteryappletimpl.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = moc_battery.cpp +OBJMOC = moc_battery.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(SYSCONF_LINK_TARGET) + +$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK_LIB) + +moc: $(SRCMOC) + +tmake: + tmake batteryapplet.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +battery.o: battery.cpp \ + battery.h \ + batterystatus.h + +batterystatus.o: batterystatus.cpp \ + batterystatus.h + +batteryappletimpl.o: batteryappletimpl.cpp \ + battery.h \ + batteryappletimpl.h + +moc_battery.o: moc_battery.cpp \ + battery.h + +moc_battery.cpp: battery.h + $(MOC) battery.h -o moc_battery.cpp + + diff --git a/core/applets/batteryapplet/battery.cpp b/core/applets/batteryapplet/battery.cpp new file mode 100644 index 0000000..3d254fc --- a/dev/null +++ b/core/applets/batteryapplet/battery.cpp @@ -0,0 +1,152 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "battery.h" +#include "batterystatus.h" + +#include + +#include +#include + + +BatteryMeter::BatteryMeter( QWidget *parent = 0 ) + : QWidget( parent ), charging(false) +{ + ps = new PowerStatus; + startTimer( 10000 ); + setFixedHeight(12); + chargeTimer = new QTimer( this ); + connect( chargeTimer, SIGNAL(timeout()), this, SLOT(chargeTimeout()) ); + timerEvent(0); +} + +BatteryMeter::~BatteryMeter() +{ + delete ps; +} + +QSize BatteryMeter::sizeHint() const +{ + return QSize(10,12); +} + +void BatteryMeter::mouseReleaseEvent( QMouseEvent *) +{ + if ( batteryView && batteryView->isVisible() ) { + delete (QWidget *) batteryView; + } else { + if ( !batteryView ) + batteryView = new BatteryStatus( ps ); + batteryView->showMaximized(); + batteryView->raise(); + batteryView->show(); + } +} + +void BatteryMeter::timerEvent( QTimerEvent * ) +{ + PowerStatus prev = *ps; + + *ps = PowerStatusManager::readStatus(); + + if ( prev != *ps ) { + percent = ps->batteryPercentRemaining(); + if ( !charging && ps->batteryStatus() == PowerStatus::Charging && percent < 0 ) { + percent = 0; + charging = true; + chargeTimer->start( 500 ); + } else if ( charging && ps->batteryStatus() != PowerStatus::Charging ) { + charging = false; + chargeTimer->stop(); + if ( batteryView ) + batteryView->updatePercent( percent ); + } + repaint(FALSE); + if ( batteryView ) + batteryView->repaint(); + } +} + +void BatteryMeter::chargeTimeout() +{ + percent += 20; + if ( percent > 100 ) + percent = 0; + + repaint(FALSE); + if ( batteryView ) + batteryView->updatePercent( percent ); +} + +void BatteryMeter::paintEvent( QPaintEvent* ) +{ + QPainter p(this); + + QColor c; + QColor darkc; + QColor lightc; + if ( ps->acStatus() == PowerStatus::Offline ) { + c = blue.light(120); + darkc = c.dark(120); + lightc = c.light(140); + } else if ( ps->acStatus() == PowerStatus::Online ) { + c = green.dark(130); + darkc = c.dark(120); + lightc = c.light(180); + } else { + c = red; + darkc = c.dark(120); + lightc = c.light(160); + } + + int w = 6; + int h = height()-3; + int pix = (percent * h) / 100; + int y2 = height() - 2; + int y = y2 - pix; + int x1 = (width() - w) / 2; + + p.setPen(QColor(80,80,80)); + p.drawLine(x1+w/4,0,x1+w/4+w/2,0); + p.drawRect(x1,1,w,height()-1); + p.setBrush(c); + + int extra = ((percent * h) % 100)/(100/4); + +#define Y(i) ((i<=extra)?y-1:y) +#define DRAWUPPER(i) if ( Y(i) >= 2 ) p.drawLine(i+x1,2,i+x1,Y(i)); + p.setPen( gray ); + DRAWUPPER(1); + DRAWUPPER(3); + p.setPen( gray.light(130) ); + DRAWUPPER(2); + p.setPen( gray.dark(120) ); + DRAWUPPER(4); + +#define DRAW(i) { if ( Y(i) < y2 ) p.drawLine(i+x1,Y(i)+1,i+x1,y2); } + p.setPen( c ); + DRAW(1); + DRAW(3); + p.setPen( lightc ); + DRAW(2); + p.setPen(darkc); + DRAW(4); +} + diff --git a/core/applets/batteryapplet/battery.h b/core/applets/batteryapplet/battery.h new file mode 100644 index 0000000..d4807b0 --- a/dev/null +++ b/core/applets/batteryapplet/battery.h @@ -0,0 +1,55 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef BATTERY_H +#define BATTERY_H + +#include +#include + +class PowerStatus; +class BatteryStatus; +class QTimer; + +class BatteryMeter : public QWidget +{ + Q_OBJECT +public: + BatteryMeter( QWidget *parent = 0 ); + ~BatteryMeter(); + + QSize sizeHint() const; + +protected: + void timerEvent( QTimerEvent * ); + void paintEvent( QPaintEvent* ); + void mouseReleaseEvent( QMouseEvent * ); + +protected slots: + void chargeTimeout(); + +protected: + QGuardedPtr batteryView; + PowerStatus *ps; + QTimer *chargeTimer; + int percent; + bool charging; +}; + +#endif diff --git a/core/applets/batteryapplet/batteryapplet.pro b/core/applets/batteryapplet/batteryapplet.pro new file mode 100644 index 0000000..fa0fca8 --- a/dev/null +++ b/core/applets/batteryapplet/batteryapplet.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += qt warn_on release +HEADERS = battery.h batterystatus.h batteryappletimpl.h +SOURCES = battery.cpp batterystatus.cpp batteryappletimpl.cpp +TARGET = batteryapplet +DESTDIR = ../../plugins/applets +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += ../$(QPEDIR)/include .. +LIBS += -lqpe +VERSION = 1.0.0 + +TRANSLATIONS += ../../i18n/de/libbatteryapplet.ts diff --git a/core/applets/batteryapplet/batteryappletimpl.cpp b/core/applets/batteryapplet/batteryappletimpl.cpp new file mode 100644 index 0000000..3f3079a --- a/dev/null +++ b/core/applets/batteryapplet/batteryappletimpl.cpp @@ -0,0 +1,63 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "battery.h" +#include "batteryappletimpl.h" + + +BatteryAppletImpl::BatteryAppletImpl() + : battery(0), ref(0) +{ +} + +BatteryAppletImpl::~BatteryAppletImpl() +{ + delete battery; +} + +QWidget *BatteryAppletImpl::applet( QWidget *parent ) +{ + if ( !battery ) + battery = new BatteryMeter( parent ); + return battery; +} + +int BatteryAppletImpl::position() const +{ + return 8; +} + +QRESULT BatteryAppletImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ + *iface = 0; + if ( uuid == IID_QUnknown ) + *iface = this; + else if ( uuid == IID_TaskbarApplet ) + *iface = this; + + if ( *iface ) + (*iface)->addRef(); + return QS_OK; +} + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( BatteryAppletImpl ) +} + diff --git a/core/applets/batteryapplet/batteryappletimpl.h b/core/applets/batteryapplet/batteryappletimpl.h new file mode 100644 index 0000000..94f49db --- a/dev/null +++ b/core/applets/batteryapplet/batteryappletimpl.h @@ -0,0 +1,44 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef BATTERYAPPLETIMPL_H +#define BATTERYAPPLETIMPL_H + +#include + +class BatteryMeter; + +class BatteryAppletImpl : public TaskbarAppletInterface +{ +public: + BatteryAppletImpl(); + virtual ~BatteryAppletImpl(); + + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT + + virtual QWidget *applet( QWidget *parent ); + virtual int position() const; + +private: + BatteryMeter *battery; + ulong ref; +}; + +#endif diff --git a/core/applets/batteryapplet/batterystatus.cpp b/core/applets/batteryapplet/batterystatus.cpp new file mode 100644 index 0000000..d18b6c9 --- a/dev/null +++ b/core/applets/batteryapplet/batterystatus.cpp @@ -0,0 +1,140 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "batterystatus.h" + +#include + +#include +#include +#include + + +BatteryStatus::BatteryStatus( const PowerStatus *p, QWidget *parent ) + : QWidget( parent, 0, WDestructiveClose), ps(p) +{ + setCaption( tr("Battery Status") ); + QPushButton *pb = new QPushButton( tr("Close"), this ); + pb->move( 70, 220 ); + pb->show(); + connect( pb, SIGNAL( clicked() ), this, SLOT( close() ) ); + percent = ps->batteryPercentRemaining(); + show(); +} + +BatteryStatus::~BatteryStatus() +{ +} + +void BatteryStatus::updatePercent( int pc ) +{ + percent = pc; + repaint(FALSE); +} + +void BatteryStatus::drawSegment( QPainter *p, const QRect &r, const QColor &topgrad, const QColor &botgrad, const QColor &highlight, int hightlight_height ) +{ + int h1, h2, s1, s2, v1, v2, ng = r.height(), hy = ng*30/100, hh = hightlight_height; + topgrad.hsv( &h1, &s1, &v1 ); + botgrad.hsv( &h2, &s2, &v2 ); + for ( int j = 0; j < hy-2; j++ ) { + p->setPen( QColor( h1 + ((h2-h1)*j)/(ng-1), s1 + ((s2-s1)*j)/(ng-1), + v1 + ((v2-v1)*j)/(ng-1), QColor::Hsv ) ); + p->drawLine( r.x(), r.top()+hy-2-j, r.x()+r.width(), r.top()+hy-2-j ); + } + for ( int j = 0; j < hh; j++ ) { + p->setPen( highlight ); + p->drawLine( r.x(), r.top()+hy-2+j, r.x()+r.width(), r.top()+hy-2+j ); + } + for ( int j = 0; j < ng-hy-hh; j++ ) { + p->setPen( QColor( h1 + ((h2-h1)*j)/(ng-1), s1 + ((s2-s1)*j)/(ng-1), + v1 + ((v2-v1)*j)/(ng-1), QColor::Hsv ) ); + p->drawLine( r.x(), r.top()+hy+hh-2+j, r.x()+r.width(), r.top()+hy+hh-2+j ); + } +} + +void BatteryStatus::paintEvent( QPaintEvent * ) +{ + QPainter p(this); + QString text; + if ( ps->batteryStatus() == PowerStatus::Charging ) { + text = tr("Charging"); + } else if ( ps->batteryPercentAccurate() ) { + text.sprintf( tr("Percentage battery remaining") + ": %i%%", percent ); + } else { + text = tr("Battery status: "); + switch ( ps->batteryStatus() ) { + case PowerStatus::High: + text += tr("Good"); + break; + case PowerStatus::Low: + text += tr("Low"); + break; + case PowerStatus::VeryLow: + text += tr("Very Low"); + break; + case PowerStatus::Critical: + text += tr("Critical"); + break; + default: // NotPresent, etc. + text += tr("Unknown"); + } + } + p.drawText( 10, 120, text ); + if ( ps->acStatus() == PowerStatus::Backup ) + p.drawText( 10, 150, tr("On backup power") ); + else if ( ps->acStatus() == PowerStatus::Online ) + p.drawText( 10, 150, tr("Power on-line") ); + else if ( ps->acStatus() == PowerStatus::Offline ) + p.drawText( 10, 150, tr("External power disconnected") ); + + if ( ps->batteryTimeRemaining() >= 0 ) { + text.sprintf( tr("Battery time remaining") + ": %im %02is", + ps->batteryTimeRemaining() / 60, ps->batteryTimeRemaining() % 60 ); + p.drawText( 10, 180, text ); + } + + QColor c; + QColor darkc; + QColor lightc; + if ( ps->acStatus() == PowerStatus::Offline ) { + c = blue.light(120); + darkc = c.dark(280); + lightc = c.light(145); + } else if ( ps->acStatus() == PowerStatus::Online ) { + c = green.dark(130); + darkc = c.dark(200); + lightc = c.light(220); + } else { + c = red; + darkc = c.dark(280); + lightc = c.light(140); + } + if ( percent < 0 ) + return; + + int percent2 = percent * 2; + p.setPen( black ); + qDrawShadePanel( &p, 9, 30, 204, 39, colorGroup(), TRUE, 1, NULL); + qDrawShadePanel( &p, 212, 37, 12, 24, colorGroup(), TRUE, 1, NULL); + drawSegment( &p, QRect( 10, 30, percent2, 40 ), lightc, darkc, lightc.light(115), 6 ); + drawSegment( &p, QRect( 11 + percent2, 30, 200 - percent2, 40 ), white.light(80), black, white.light(90), 6 ); + drawSegment( &p, QRect( 212, 37, 10, 25 ), white.light(80), black, white.light(90), 2 ); +} + diff --git a/core/applets/batteryapplet/batterystatus.h b/core/applets/batteryapplet/batterystatus.h new file mode 100644 index 0000000..85b2c4d --- a/dev/null +++ b/core/applets/batteryapplet/batterystatus.h @@ -0,0 +1,45 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef BATTERY_STATUS_H +#define BATTERY_STATUS_H + +#include + +class PowerStatus; + +class BatteryStatus : public QWidget +{ +public: + BatteryStatus( const PowerStatus *s, QWidget *parent=0 ); + ~BatteryStatus(); + + void updatePercent( int ); + +protected: + void drawSegment( QPainter *p, const QRect &r, const QColor &topgrad, const QColor &botgrad, const QColor &highlight, int hightlight_height ); + void paintEvent( QPaintEvent *pe ); + +private: + const PowerStatus *ps; + int percent; +}; + +#endif + diff --git a/core/applets/batteryapplet/qpe-batteryapplet.control b/core/applets/batteryapplet/qpe-batteryapplet.control new file mode 100644 index 0000000..83d0b8b --- a/dev/null +++ b/core/applets/batteryapplet/qpe-batteryapplet.control @@ -0,0 +1,9 @@ +Files: plugins/applets/libbatteryapplet.so* +Priority: optional +Section: qpe/taskbar +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: Battery Monitor applet + Battery Monitor applet for the Qtopia environment taskbar. diff --git a/core/applets/batteryapplet/qpe-batteryapplet.postinst b/core/applets/batteryapplet/qpe-batteryapplet.postinst new file mode 100755 index 0000000..ba76ffa --- a/dev/null +++ b/core/applets/batteryapplet/qpe-batteryapplet.postinst @@ -0,0 +1,2 @@ +#!/bin/sh +/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadApplets()" diff --git a/core/applets/batteryapplet/qpe-batteryapplet.postrm b/core/applets/batteryapplet/qpe-batteryapplet.postrm new file mode 100755 index 0000000..ba76ffa --- a/dev/null +++ b/core/applets/batteryapplet/qpe-batteryapplet.postrm @@ -0,0 +1,2 @@ +#!/bin/sh +/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadApplets()" diff --git a/core/applets/clipboardapplet/Makefile.in b/core/applets/clipboardapplet/Makefile.in new file mode 100644 index 0000000..2ddeb42 --- a/dev/null +++ b/core/applets/clipboardapplet/Makefile.in @@ -0,0 +1,115 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../../plugins/applets/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = clipboardapplet +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = clipboard.h \ + clipboardappletimpl.h +SOURCES = clipboard.cpp \ + clipboardappletimpl.cpp +OBJECTS = clipboard.o \ + clipboardappletimpl.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = moc_clipboard.cpp +OBJMOC = moc_clipboard.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(SYSCONF_LINK_TARGET) + +$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK_LIB) + +moc: $(SRCMOC) + +tmake: + tmake clipboardapplet.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +clipboard.o: clipboard.cpp \ + clipboard.h + +clipboardappletimpl.o: clipboardappletimpl.cpp \ + clipboard.h \ + clipboardappletimpl.h + +moc_clipboard.o: moc_clipboard.cpp \ + clipboard.h + +moc_clipboard.cpp: clipboard.h + $(MOC) clipboard.h -o moc_clipboard.cpp + + diff --git a/core/applets/clipboardapplet/clipboard.cpp b/core/applets/clipboardapplet/clipboard.cpp new file mode 100644 index 0000000..57beffc --- a/dev/null +++ b/core/applets/clipboardapplet/clipboard.cpp @@ -0,0 +1,80 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "clipboard.h" + +#include + +#include +#include +#include + + +//=========================================================================== + +ClipboardApplet::ClipboardApplet( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + setFixedWidth( 14 ); + clipboardPixmap = Resource::loadPixmap( "clipboard" ); + menu = 0; +} + +ClipboardApplet::~ClipboardApplet() +{ +} + +void ClipboardApplet::mousePressEvent( QMouseEvent *) +{ + if ( !menu ) { + menu = new QPopupMenu(this); + menu->insertItem(tr("Cut")); + menu->insertItem(tr("Copy")); + menu->insertItem(tr("Paste")); + connect(menu, SIGNAL(selected(int)), this, SLOT(action(int))); + } + menu->popup(mapToGlobal(QPoint(0,0))); +} + +void ClipboardApplet::action(int i) +{ + ushort unicode=0; + int scan=0; + + if ( i == 0 ) + { unicode='X'-'@'; scan=Key_X; } // Cut + else if ( i == 1 ) + { unicode='C'-'@'; scan=Key_C; } // Copy + else if ( i == 2 ) + { unicode='V'-'@'; scan=Key_V; } // Paste + + if ( scan ) { + qwsServer->processKeyEvent( unicode, scan, ControlButton, TRUE, FALSE ); + qwsServer->processKeyEvent( unicode, scan, ControlButton, FALSE, FALSE ); + } +} + +void ClipboardApplet::paintEvent( QPaintEvent* ) +{ + QPainter p(this); + p.drawPixmap( 0, 1, clipboardPixmap ); +} + + diff --git a/core/applets/clipboardapplet/clipboard.h b/core/applets/clipboardapplet/clipboard.h new file mode 100644 index 0000000..9dd59ed --- a/dev/null +++ b/core/applets/clipboardapplet/clipboard.h @@ -0,0 +1,47 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __CLIPBOARD_APPLET_H__ +#define __CLIPBOARD_APPLET_H__ + +#include +#include + +class ClipboardApplet : public QWidget +{ + Q_OBJECT +public: + ClipboardApplet( QWidget *parent = 0, const char *name=0 ); + ~ClipboardApplet(); + +protected: + void mousePressEvent( QMouseEvent *); + void paintEvent( QPaintEvent* ); + +private slots: + void action(int); + +private: + QPopupMenu* menu; + QPixmap clipboardPixmap; +}; + + +#endif // __CLIPBOARD_APPLET_H__ + diff --git a/core/applets/clipboardapplet/clipboardapplet.pro b/core/applets/clipboardapplet/clipboardapplet.pro new file mode 100644 index 0000000..b0624ef --- a/dev/null +++ b/core/applets/clipboardapplet/clipboardapplet.pro @@ -0,0 +1,10 @@ +TEMPLATE = lib +CONFIG += qt warn_on release +HEADERS = clipboard.h clipboardappletimpl.h +SOURCES = clipboard.cpp clipboardappletimpl.cpp +TARGET = clipboardapplet +DESTDIR = ../../plugins/applets +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += ../$(QPEDIR)/include +LIBS += -lqpe +VERSION = 1.0.0 diff --git a/core/applets/clipboardapplet/clipboardappletimpl.cpp b/core/applets/clipboardapplet/clipboardappletimpl.cpp new file mode 100644 index 0000000..8080690 --- a/dev/null +++ b/core/applets/clipboardapplet/clipboardappletimpl.cpp @@ -0,0 +1,64 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "clipboard.h" +#include "clipboardappletimpl.h" + + +ClipboardAppletImpl::ClipboardAppletImpl() + : clipboard(0), ref(0) +{ +} + +ClipboardAppletImpl::~ClipboardAppletImpl() +{ + delete clipboard; +} + +QWidget *ClipboardAppletImpl::applet( QWidget *parent ) +{ + if ( !clipboard ) + clipboard = new ClipboardApplet( parent ); + return clipboard; +} + +int ClipboardAppletImpl::position() const +{ + return 6; +} + +QRESULT ClipboardAppletImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ + *iface = 0; + if ( uuid == IID_QUnknown ) + *iface = this; + else if ( uuid == IID_TaskbarApplet ) + *iface = this; + + if ( *iface ) + (*iface)->addRef(); + return QS_OK; +} + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( ClipboardAppletImpl ) +} + + diff --git a/core/applets/clipboardapplet/clipboardappletimpl.h b/core/applets/clipboardapplet/clipboardappletimpl.h new file mode 100644 index 0000000..0426109 --- a/dev/null +++ b/core/applets/clipboardapplet/clipboardappletimpl.h @@ -0,0 +1,44 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef CLIPBOARDAPPLETIMPL_H +#define CLIPBOARDAPPLETIMPL_H + +#include + +class ClipboardApplet; + +class ClipboardAppletImpl : public TaskbarAppletInterface +{ +public: + ClipboardAppletImpl(); + virtual ~ClipboardAppletImpl(); + + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT + + virtual QWidget *applet( QWidget *parent ); + virtual int position() const; + +private: + ClipboardApplet *clipboard; + ulong ref; +}; + +#endif diff --git a/core/applets/clipboardapplet/qpe-clipboardapplet.control b/core/applets/clipboardapplet/qpe-clipboardapplet.control new file mode 100644 index 0000000..26cbc55 --- a/dev/null +++ b/core/applets/clipboardapplet/qpe-clipboardapplet.control @@ -0,0 +1,9 @@ +Files: plugins/applets/libclipboardapplet.so* +Priority: optional +Section: qpe/taskbar +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: Clipboard applet + Clipboard applet for the Qtopia environment taskbar. diff --git a/core/applets/clipboardapplet/qpe-clipboardapplet.postinst b/core/applets/clipboardapplet/qpe-clipboardapplet.postinst new file mode 100644 index 0000000..ba76ffa --- a/dev/null +++ b/core/applets/clipboardapplet/qpe-clipboardapplet.postinst @@ -0,0 +1,2 @@ +#!/bin/sh +/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadApplets()" diff --git a/core/applets/clipboardapplet/qpe-clipboardapplet.postrm b/core/applets/clipboardapplet/qpe-clipboardapplet.postrm new file mode 100644 index 0000000..ba76ffa --- a/dev/null +++ b/core/applets/clipboardapplet/qpe-clipboardapplet.postrm @@ -0,0 +1,2 @@ +#!/bin/sh +/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadApplets()" diff --git a/core/applets/clockapplet/.cvsignore b/core/applets/clockapplet/.cvsignore new file mode 100644 index 0000000..edfa921 --- a/dev/null +++ b/core/applets/clockapplet/.cvsignore @@ -0,0 +1,3 @@ +moc_* +*.moc +Makefile diff --git a/core/applets/clockapplet/Makefile.in b/core/applets/clockapplet/Makefile.in new file mode 100644 index 0000000..fcf737e --- a/dev/null +++ b/core/applets/clockapplet/Makefile.in @@ -0,0 +1,115 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../../plugins/applets/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = clockapplet +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = clock.h \ + clockappletimpl.h +SOURCES = clock.cpp \ + clockappletimpl.cpp +OBJECTS = clock.o \ + clockappletimpl.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = moc_clock.cpp +OBJMOC = moc_clock.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(SYSCONF_LINK_TARGET) + +$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK_LIB) + +moc: $(SRCMOC) + +tmake: + tmake clockapplet.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +clock.o: clock.cpp \ + clock.h + +clockappletimpl.o: clockappletimpl.cpp \ + clock.h \ + clockappletimpl.h + +moc_clock.o: moc_clock.cpp \ + clock.h + +moc_clock.cpp: clock.h + $(MOC) clock.h -o moc_clock.cpp + + diff --git a/core/applets/clockapplet/clock.cpp b/core/applets/clockapplet/clock.cpp new file mode 100644 index 0000000..178dcbe --- a/dev/null +++ b/core/applets/clockapplet/clock.cpp @@ -0,0 +1,97 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "clock.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +LauncherClock::LauncherClock( QWidget *parent ) : QLabel( parent ) +{ + // If you want a sunken border around the clock do this: + // setFrameStyle( QFrame::Panel | QFrame::Sunken ); + setFont( QFont( "Helvetica", 10, QFont::Normal ) ); + connect( qApp, SIGNAL( timeChanged() ), this, SLOT( updateTime( ) ) ); + connect( qApp, SIGNAL( clockChanged( bool ) ), + this, SLOT( slotClockChanged( bool ) ) ); + Config config( "qpe" ); + config.setGroup( "Time" ); + ampmFormat = config.readBoolEntry( "AMPM", TRUE ); + timerId = 0; + timerEvent( 0 ); + show(); +} + +void LauncherClock::mouseReleaseEvent( QMouseEvent * ) +{ + Global::execute( "systemtime" ); +} + + +void LauncherClock::timerEvent( QTimerEvent *e ) +{ + if ( !e || e->timerId() == timerId ) { + killTimer( timerId ); + changeTime(); + QTime t = QTime::currentTime(); + int ms = (60 - t.second())*1000 - t.msec(); + timerId = startTimer( ms ); + } else { + QLabel::timerEvent( e ); + } +} + +void LauncherClock::updateTime( void ) +{ + changeTime(); +} + +void LauncherClock::changeTime( void ) +{ + QTime tm = QDateTime::currentDateTime().time(); + QString s; + if( ampmFormat ) { + int hour = tm.hour(); + if (hour == 0) + hour = 12; + if (hour > 12) + hour -= 12; + s.sprintf( "%2d%c%02d %s", hour, ':', tm.minute(), (tm.hour() >= 12) ? "PM" : "AM" ); + } else + s.sprintf( "%2d%c%02d", tm.hour(), ':', tm.minute() ); + setText( s ); +} + +void LauncherClock::slotClockChanged( bool pm ) +{ + ampmFormat = pm; + updateTime(); +} diff --git a/core/applets/clockapplet/clock.h b/core/applets/clockapplet/clock.h new file mode 100644 index 0000000..9670d90 --- a/dev/null +++ b/core/applets/clockapplet/clock.h @@ -0,0 +1,46 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __LAUNCHER_CLOCK_H__ +#define __LAUNCHER_CLOCK_H__ + + +#include +#include + +class LauncherClock : public QLabel +{ + Q_OBJECT +public: + LauncherClock( QWidget *parent ); + +protected slots: + void updateTime( void ); + void slotClockChanged( bool pm ); + +protected: + void mouseReleaseEvent( QMouseEvent * ); + void timerEvent( QTimerEvent * ); + void changeTime( void ); + bool ampmFormat; + int timerId; +}; + + +#endif // __LAUNCHER_CLOCK_H__ diff --git a/core/applets/clockapplet/clockapplet.pro b/core/applets/clockapplet/clockapplet.pro new file mode 100644 index 0000000..29a4e8b --- a/dev/null +++ b/core/applets/clockapplet/clockapplet.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += qt warn_on release +HEADERS = clock.h clockappletimpl.h +SOURCES = clock.cpp clockappletimpl.cpp +TARGET = clockapplet +DESTDIR = ../../plugins/applets +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += ../$(QPEDIR)/include .. +LIBS += -lqpe +VERSION = 1.0.0 + +TRANSLATIONS += ../../i18n/de/libclockapplet.ts diff --git a/core/applets/clockapplet/clockappletimpl.cpp b/core/applets/clockapplet/clockappletimpl.cpp new file mode 100644 index 0000000..8bf1baf --- a/dev/null +++ b/core/applets/clockapplet/clockappletimpl.cpp @@ -0,0 +1,65 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "clock.h" +#include "clockappletimpl.h" + + +ClockAppletImpl::ClockAppletImpl() + : clock(0), ref(0) +{ +} + +ClockAppletImpl::~ClockAppletImpl() +{ + delete clock; +} + +QWidget *ClockAppletImpl::applet( QWidget *parent ) +{ + if ( !clock ) + clock = new LauncherClock( parent ); + return clock; +} + +int ClockAppletImpl::position() const +{ + return 10; +} + +#ifndef QT_NO_COMPONENT +QRESULT ClockAppletImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ + *iface = 0; + if ( uuid == IID_QUnknown ) + *iface = this; + else if ( uuid == IID_TaskbarApplet ) + *iface = this; + + if ( *iface ) + (*iface)->addRef(); + return QS_OK; +} + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( ClockAppletImpl ) +} +#endif + diff --git a/core/applets/clockapplet/clockappletimpl.h b/core/applets/clockapplet/clockappletimpl.h new file mode 100644 index 0000000..0c0912e --- a/dev/null +++ b/core/applets/clockapplet/clockappletimpl.h @@ -0,0 +1,46 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef CLOCKAPPLETIMPL_H +#define CLOCKAPPLETIMPL_H + +#include + +class LauncherClock; + +class ClockAppletImpl : public TaskbarAppletInterface +{ +public: + ClockAppletImpl(); + virtual ~ClockAppletImpl(); + +#ifndef QT_NO_COMPONENT + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT +#endif + + virtual QWidget *applet( QWidget *parent ); + virtual int position() const; + +private: + LauncherClock *clock; + ulong ref; +}; + +#endif diff --git a/core/applets/clockapplet/qpe-clockapplet.control b/core/applets/clockapplet/qpe-clockapplet.control new file mode 100644 index 0000000..9532ca8 --- a/dev/null +++ b/core/applets/clockapplet/qpe-clockapplet.control @@ -0,0 +1,9 @@ +Files: plugins/applets/libclockapplet.so* +Priority: optional +Section: qpe/taskbar +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: Clock applet + Clock applet for the Qtopia environment taskbar. diff --git a/core/applets/clockapplet/qpe-clockapplet.postinst b/core/applets/clockapplet/qpe-clockapplet.postinst new file mode 100755 index 0000000..ba76ffa --- a/dev/null +++ b/core/applets/clockapplet/qpe-clockapplet.postinst @@ -0,0 +1,2 @@ +#!/bin/sh +/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadApplets()" diff --git a/core/applets/clockapplet/qpe-clockapplet.postrm b/core/applets/clockapplet/qpe-clockapplet.postrm new file mode 100755 index 0000000..ba76ffa --- a/dev/null +++ b/core/applets/clockapplet/qpe-clockapplet.postrm @@ -0,0 +1,2 @@ +#!/bin/sh +/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadApplets()" diff --git a/core/applets/volumeapplet/.cvsignore b/core/applets/volumeapplet/.cvsignore new file mode 100644 index 0000000..edfa921 --- a/dev/null +++ b/core/applets/volumeapplet/.cvsignore @@ -0,0 +1,3 @@ +moc_* +*.moc +Makefile diff --git a/core/applets/volumeapplet/Makefile.in b/core/applets/volumeapplet/Makefile.in new file mode 100644 index 0000000..7020cb7 --- a/dev/null +++ b/core/applets/volumeapplet/Makefile.in @@ -0,0 +1,115 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../../plugins/applets/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = volumeapplet +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = volume.h \ + volumeappletimpl.h +SOURCES = volume.cpp \ + volumeappletimpl.cpp +OBJECTS = volume.o \ + volumeappletimpl.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = moc_volume.cpp +OBJMOC = moc_volume.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(SYSCONF_LINK_TARGET) + +$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK_LIB) + +moc: $(SRCMOC) + +tmake: + tmake volumeapplet.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +volume.o: volume.cpp \ + volume.h + +volumeappletimpl.o: volumeappletimpl.cpp \ + volume.h \ + volumeappletimpl.h + +moc_volume.o: moc_volume.cpp \ + volume.h + +moc_volume.cpp: volume.h + $(MOC) volume.h -o moc_volume.cpp + + diff --git a/core/applets/volumeapplet/qpe-volumeapplet.control b/core/applets/volumeapplet/qpe-volumeapplet.control new file mode 100644 index 0000000..a80262a --- a/dev/null +++ b/core/applets/volumeapplet/qpe-volumeapplet.control @@ -0,0 +1,9 @@ +Files: plugins/applets/libvolumeapplet.so* +Priority: optional +Section: qpe/taskbar +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: Volume applet + Volume applet for the Qtopia environment taskbar. diff --git a/core/applets/volumeapplet/qpe-volumeapplet.postinst b/core/applets/volumeapplet/qpe-volumeapplet.postinst new file mode 100755 index 0000000..ba76ffa --- a/dev/null +++ b/core/applets/volumeapplet/qpe-volumeapplet.postinst @@ -0,0 +1,2 @@ +#!/bin/sh +/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadApplets()" diff --git a/core/applets/volumeapplet/qpe-volumeapplet.postrm b/core/applets/volumeapplet/qpe-volumeapplet.postrm new file mode 100755 index 0000000..ba76ffa --- a/dev/null +++ b/core/applets/volumeapplet/qpe-volumeapplet.postrm @@ -0,0 +1,2 @@ +#!/bin/sh +/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadApplets()" diff --git a/core/applets/volumeapplet/volume.cpp b/core/applets/volumeapplet/volume.cpp new file mode 100644 index 0000000..35dbf22 --- a/dev/null +++ b/core/applets/volumeapplet/volume.cpp @@ -0,0 +1,199 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "volume.h" + +#include +#include +#include +#if ( defined Q_WS_QWS || defined(_WS_QWS_) ) && !defined(QT_NO_COP) +#include +#endif + +#include +#include +#include +#include +#include +#include + + +VolumeControl::VolumeControl( QWidget *parent, const char *name ) + : QFrame( parent, name, WDestructiveClose | WStyle_StaysOnTop | WType_Popup ) +{ + setFrameStyle( QFrame::PopupPanel | QFrame::Raised ); + + QVBoxLayout *vbox = new QVBoxLayout( this ); + slider = new QSlider( this ); + muteBox = new QCheckBox( tr("Mute"), this ); + slider->setRange( 0, 100 ); + slider->setTickmarks( QSlider::Both ); + slider->setTickInterval( 20 ); + slider->setFocusPolicy( QWidget::NoFocus ); + muteBox->setFocusPolicy( QWidget::NoFocus ); + vbox->setMargin( 6 ); + vbox->setSpacing( 3 ); + vbox->addWidget( slider, 0, Qt::AlignVCenter | Qt::AlignHCenter ); + vbox->addWidget( muteBox ); + setFixedHeight( 100 ); + setFixedWidth( sizeHint().width() ); + setFocusPolicy(QWidget::NoFocus); +} + +void VolumeControl::keyPressEvent( QKeyEvent *e) +{ + switch(e->key()) { + case Key_Up: + slider->subtractStep(); + break; + case Key_Down: + slider->addStep(); + break; + case Key_Space: + muteBox->toggle(); + break; + case Key_Escape: + close(); + break; + } +} + +//=========================================================================== + +VolumeApplet::VolumeApplet( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + setFixedHeight( 18 ); + setFixedWidth( 14 ); + volumePixmap = Resource::loadPixmap( "volume" ); + muted = FALSE; // ### read from pref + volumePercent = 50; // ### read from pref + connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( volumeChanged(bool) ) ); + writeSystemVolume(); +} + +VolumeApplet::~VolumeApplet() +{ +} + +void VolumeApplet::mousePressEvent( QMouseEvent *) +{ + // Create a small volume control window to adjust the volume with + VolumeControl *vc = new VolumeControl; + vc->slider->setValue( 100 - volumePercent ); + vc->muteBox->setChecked( muted ); + connect( vc->slider, SIGNAL( valueChanged( int ) ), this, SLOT( sliderMoved( int ) ) ); + connect( vc->muteBox, SIGNAL( toggled( bool ) ), this, SLOT( mute( bool ) ) ); + QPoint curPos = mapToGlobal( rect().topLeft() ); + vc->move( curPos.x()-(vc->sizeHint().width()-width())/2, curPos.y() - 100 ); + vc->show(); +} + +void VolumeApplet::volumeChanged( bool nowMuted ) +{ + int previousVolume = volumePercent; + + if ( !nowMuted ) + readSystemVolume(); + + // Handle case where muting it toggled + if ( muted != nowMuted ) { + muted = nowMuted; + repaint( TRUE ); + return; + } + + // Avoid over repainting + if ( previousVolume != volumePercent ) + repaint( 2, height() - 3, width() - 4, 2, FALSE ); +} + + +void VolumeApplet::mute( bool toggled ) +{ + muted = toggled; + // clear if removing mute + repaint( !toggled ); + writeSystemVolume(); +} + + +void VolumeApplet::sliderMoved( int percent ) +{ + setVolume( 100 - percent ); +} + + +void VolumeApplet::readSystemVolume() +{ + Config cfg("Sound"); + cfg.setGroup("System"); + volumePercent = cfg.readNumEntry("Volume"); +} + + +void VolumeApplet::setVolume( int percent ) +{ + // clamp volume percent to be between 0 and 100 + volumePercent = (percent < 0) ? 0 : ((percent > 100) ? 100 : percent); + // repaint just the little volume rectangle + repaint( 2, height() - 3, width() - 4, 2, FALSE ); + writeSystemVolume(); +} + + +void VolumeApplet::writeSystemVolume() +{ + { + Config cfg("Sound"); + cfg.setGroup("System"); + cfg.writeEntry("Volume",volumePercent); + } +#if ( defined Q_WS_QWS || defined(_WS_QWS_) ) && !defined(QT_NO_COP) + // Send notification that the volume has changed + QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << muted; +#endif +} + + +void VolumeApplet::paintEvent( QPaintEvent* ) +{ + QPainter p(this); + + if (volumePixmap.isNull()) + volumePixmap = Resource::loadPixmap( "volume" ); + p.drawPixmap( 0, 1, volumePixmap ); + p.setPen( darkGray ); + p.drawRect( 1, height() - 4, width() - 2, 4 ); + + int pixelsWide = volumePercent * (width() - 4) / 100; + p.fillRect( 2, height() - 3, pixelsWide, 2, red ); + p.fillRect( pixelsWide + 2, height() - 3, width() - 4 - pixelsWide, 2, lightGray ); + + if ( muted ) { + p.setPen( red ); + p.drawLine( 1, 2, width() - 2, height() - 5 ); + p.drawLine( 1, 3, width() - 2, height() - 4 ); + p.drawLine( width() - 2, 2, 1, height() - 5 ); + p.drawLine( width() - 2, 3, 1, height() - 4 ); + } +} + + diff --git a/core/applets/volumeapplet/volume.h b/core/applets/volumeapplet/volume.h new file mode 100644 index 0000000..5704cad --- a/dev/null +++ b/core/applets/volumeapplet/volume.h @@ -0,0 +1,75 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __VOLUME_APPLET_H__ +#define __VOLUME_APPLET_H__ + + +#include +#include +#include +#include + +class QSlider; +class QCheckBox; + +class VolumeControl : public QFrame +{ + Q_OBJECT +public: + VolumeControl( QWidget *parent=0, const char *name=0 ); + +public: + QSlider *slider; + QCheckBox *muteBox; + +private: + void keyPressEvent( QKeyEvent * ); +}; + +class VolumeApplet : public QWidget +{ + Q_OBJECT +public: + VolumeApplet( QWidget *parent = 0, const char *name=0 ); + ~VolumeApplet(); + bool isMute( ) { return muted; } + int percent( ) { return volumePercent; } + +public slots: + void volumeChanged( bool muted ); + void setVolume( int percent ); + void sliderMoved( int percent ); + void mute( bool ); + +private: + void readSystemVolume(); + void writeSystemVolume(); + void mousePressEvent( QMouseEvent * ); + void paintEvent( QPaintEvent* ); + +private: + int volumePercent; + bool muted; + QPixmap volumePixmap; +}; + + +#endif // __VOLUME_APPLET_H__ + diff --git a/core/applets/volumeapplet/volumeapplet.pro b/core/applets/volumeapplet/volumeapplet.pro new file mode 100644 index 0000000..a33cf81 --- a/dev/null +++ b/core/applets/volumeapplet/volumeapplet.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += qt warn_on release +HEADERS = volume.h volumeappletimpl.h +SOURCES = volume.cpp volumeappletimpl.cpp +TARGET = volumeapplet +DESTDIR = ../../plugins/applets +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += ../$(QPEDIR)/include +LIBS += -lqpe +VERSION = 1.0.0 + +TRANSLATIONS += ../../i18n/de/libvolumeapplet.ts diff --git a/core/applets/volumeapplet/volumeappletimpl.cpp b/core/applets/volumeapplet/volumeappletimpl.cpp new file mode 100644 index 0000000..676ab61 --- a/dev/null +++ b/core/applets/volumeapplet/volumeappletimpl.cpp @@ -0,0 +1,64 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "volume.h" +#include "volumeappletimpl.h" + + +VolumeAppletImpl::VolumeAppletImpl() + : volume(0), ref(0) +{ +} + +VolumeAppletImpl::~VolumeAppletImpl() +{ + delete volume; +} + +QWidget *VolumeAppletImpl::applet( QWidget *parent ) +{ + if ( !volume ) + volume = new VolumeApplet( parent ); + return volume; +} + +int VolumeAppletImpl::position() const +{ + return 6; +} + +QRESULT VolumeAppletImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ + *iface = 0; + if ( uuid == IID_QUnknown ) + *iface = this; + else if ( uuid == IID_TaskbarApplet ) + *iface = this; + + if ( *iface ) + (*iface)->addRef(); + return QS_OK; +} + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( VolumeAppletImpl ) +} + + diff --git a/core/applets/volumeapplet/volumeappletimpl.h b/core/applets/volumeapplet/volumeappletimpl.h new file mode 100644 index 0000000..9b2952a --- a/dev/null +++ b/core/applets/volumeapplet/volumeappletimpl.h @@ -0,0 +1,44 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef VOLUMEAPPLETIMPL_H +#define VOLUMEAPPLETIMPL_H + +#include + +class VolumeApplet; + +class VolumeAppletImpl : public TaskbarAppletInterface +{ +public: + VolumeAppletImpl(); + virtual ~VolumeAppletImpl(); + + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT + + virtual QWidget *applet( QWidget *parent ); + virtual int position() const; + +private: + VolumeApplet *volume; + ulong ref; +}; + +#endif diff --git a/core/apps/calibrate/.cvsignore b/core/apps/calibrate/.cvsignore new file mode 100644 index 0000000..edfa921 --- a/dev/null +++ b/core/apps/calibrate/.cvsignore @@ -0,0 +1,3 @@ +moc_* +*.moc +Makefile diff --git a/core/apps/calibrate/calibrate.cpp b/core/apps/calibrate/calibrate.cpp new file mode 100644 index 0000000..96cd1ca --- a/dev/null +++ b/core/apps/calibrate/calibrate.cpp @@ -0,0 +1,243 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "calibrate.h" + +#include + +#include + +#if defined(Q_WS_QWS) || defined(_WS_QWS_) + +#include +#include +#include +#include + + +Calibrate::Calibrate(QWidget* parent, const char * name, WFlags wf) : + QDialog( parent, name, TRUE, wf | WStyle_Tool | WStyle_Customize | WStyle_StaysOnTop ) +{ + showCross = TRUE; + const int offset = 30; + QRect desk = qApp->desktop()->geometry(); + setGeometry( 0, 0, desk.width(), desk.height() ); + if ( desk.height() < 250 ) { + int w = desk.height()/3; + logo.convertFromImage(Resource::loadImage("qtlogo").smoothScale(w,w)); + } else { + logo = Resource::loadPixmap( "qtlogo" ); + } + cd.screenPoints[QWSPointerCalibrationData::TopLeft] = QPoint( offset, offset ); + cd.screenPoints[QWSPointerCalibrationData::BottomLeft] = QPoint( offset, qt_screen->deviceHeight() - offset ); + cd.screenPoints[QWSPointerCalibrationData::BottomRight] = QPoint( qt_screen->deviceWidth() - offset, qt_screen->deviceHeight() - offset ); + cd.screenPoints[QWSPointerCalibrationData::TopRight] = QPoint( qt_screen->deviceWidth() - offset, offset ); + cd.screenPoints[QWSPointerCalibrationData::Center] = QPoint( qt_screen->deviceWidth()/2, qt_screen->deviceHeight()/2 ); + goodcd = cd; + reset(); + + timer = new QTimer( this ); + connect( timer, SIGNAL(timeout()), this, SLOT(timeout()) ); +} + +Calibrate::~Calibrate() +{ + store(); +} + +void Calibrate::show() +{ + grabMouse(); + QWSServer::mouseHandler()->getCalibration(&goodcd); + QWSServer::mouseHandler()->clearCalibration(); + QDialog::show(); +} + +void Calibrate::store() +{ + QWSServer::mouseHandler()->calibrate( &goodcd ); +} + +void Calibrate::hide() +{ + if ( isVisible() ) + store(); + QDialog::hide(); +} + +void Calibrate::reset() +{ + penPos = QPoint(); + location = QWSPointerCalibrationData::TopLeft; + crossPos = fromDevice( cd.screenPoints[location] ); +} + +QPoint Calibrate::fromDevice( const QPoint &p ) +{ + return qt_screen->mapFromDevice( p, + QSize(qt_screen->deviceWidth(), qt_screen->deviceHeight()) ); +} + +bool Calibrate::sanityCheck() +{ + QPoint tl = cd.devPoints[QWSPointerCalibrationData::TopLeft]; + QPoint tr = cd.devPoints[QWSPointerCalibrationData::TopRight]; + QPoint bl = cd.devPoints[QWSPointerCalibrationData::BottomLeft]; + QPoint br = cd.devPoints[QWSPointerCalibrationData::BottomRight]; + + int vl = QABS( tl.y() - bl.y() ); + int vr = QABS( tr.y() - br.y() ); + int diff = QABS( vl - vr ); + int avg = ( vl + vr ) / 2; + if ( diff > avg / 20 ) // 5% leeway + return FALSE; + + int ht = QABS( tl.x() - tr.x() ); + int hb = QABS( br.x() - bl.x() ); + diff = QABS( ht - hb ); + avg = ( ht + hb ) / 2; + if ( diff > avg / 20 ) // 5% leeway + return FALSE; + + return TRUE; +} + +void Calibrate::moveCrosshair( QPoint pt ) +{ +/* + QPainter p( this ); + p.drawPixmap( crossPos.x()-8, crossPos.y()-8, saveUnder ); + saveUnder = QPixmap::grabWindow( winId(), pt.x()-8, pt.y()-8, 16, 16 ); + p.drawRect( pt.x()-1, pt.y()-8, 2, 7 ); + p.drawRect( pt.x()-1, pt.y()+1, 2, 7 ); + p.drawRect( pt.x()-8, pt.y()-1, 7, 2 ); + p.drawRect( pt.x()+1, pt.y()-1, 7, 2 ); +*/ + showCross = FALSE; + repaint( crossPos.x()-8, crossPos.y()-8, 16, 16 ); + showCross = TRUE; + crossPos = pt; + repaint( crossPos.x()-8, crossPos.y()-8, 16, 16 ); +} + +void Calibrate::paintEvent( QPaintEvent * ) +{ + QPainter p( this ); + + int y; + + if ( !logo.isNull() ) { + y = height() / 2 - logo.height() - 15; + p.drawPixmap( (width() - logo.width())/2, y, logo ); + } + + y = height() / 2 + 15; + + p.drawText( 0, y+height()/8, width(), height() - y, AlignHCenter, + tr("Touch the crosshairs firmly and\n" + "accurately to calibrate your screen.") ); + + QFont f = p.font(); f.setBold(TRUE); + p.setFont( f ); + p.drawText( 0, y, width(), height() - y, AlignHCenter|WordBreak, + tr("Welcome to Qtopia") ); + +/* + saveUnder = QPixmap::grabWindow( winId(), crossPos.x()-8, crossPos.y()-8, + 16, 16 ); + moveCrosshair( crossPos ); +*/ + if ( showCross ) { + p.drawRect( crossPos.x()-1, crossPos.y()-8, 2, 7 ); + p.drawRect( crossPos.x()-1, crossPos.y()+1, 2, 7 ); + p.drawRect( crossPos.x()-8, crossPos.y()-1, 7, 2 ); + p.drawRect( crossPos.x()+1, crossPos.y()-1, 7, 2 ); + } +} + +void Calibrate::mousePressEvent( QMouseEvent *e ) +{ + // map to device coordinates + QPoint devPos = qt_screen->mapToDevice( e->pos(), + QSize(qt_screen->width(), qt_screen->height()) ); + if ( penPos.isNull() ) + penPos = devPos; + else + penPos = QPoint( (penPos.x() + devPos.x())/2, + (penPos.y() + devPos.y())/2 ); +} + +void Calibrate::mouseReleaseEvent( QMouseEvent * ) +{ + if ( timer->isActive() ) + return; + + bool doMove = TRUE; + + cd.devPoints[location] = penPos; + if ( location < QWSPointerCalibrationData::LastLocation ) { + location = (QWSPointerCalibrationData::Location)((int)location + 1); + } else { + if ( sanityCheck() ) { + reset(); + goodcd = cd; + hide(); + emit accept(); + doMove = FALSE; + } else { + location = QWSPointerCalibrationData::TopLeft; + } + } + + if ( doMove ) { + QPoint target = fromDevice( cd.screenPoints[location] ); + dx = (target.x() - crossPos.x())/10; + dy = (target.y() - crossPos.y())/10; + timer->start( 30 ); + } +} + +void Calibrate::timeout() +{ + QPoint target = fromDevice( cd.screenPoints[location] ); + + bool doneX = FALSE; + bool doneY = FALSE; + QPoint newPos( crossPos.x() + dx, crossPos.y() + dy ); + + if ( QABS(crossPos.x() - target.x()) <= QABS(dx) ) { + newPos.setX( target.x() ); + doneX = TRUE; + } + + if ( QABS(crossPos.y() - target.y()) <= QABS(dy) ) { + newPos.setY(target.y()); + doneY = TRUE; + } + + if ( doneX && doneY ) { + penPos = QPoint(); + timer->stop(); + } + + moveCrosshair( newPos ); +} + +#endif // _WS_QWS_ diff --git a/core/apps/calibrate/calibrate.h b/core/apps/calibrate/calibrate.h new file mode 100644 index 0000000..97108c9 --- a/dev/null +++ b/core/apps/calibrate/calibrate.h @@ -0,0 +1,67 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include + +#if defined(Q_WS_QWS) || defined(_WS_QWS_) + +#include +#include + +class QTimer; + +class Calibrate : public QDialog +{ + Q_OBJECT +public: + Calibrate(QWidget* parent=0, const char * name=0, WFlags=0); + ~Calibrate(); + + void show(); + void hide(); + +private: + QPoint fromDevice( const QPoint &p ); + bool sanityCheck(); + void moveCrosshair( QPoint pt ); + void paintEvent( QPaintEvent * ); + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + +private slots: + void timeout(); + +private: + void store(); + void reset(); + QPixmap logo; + QWSPointerCalibrationData goodcd,cd; + QWSPointerCalibrationData::Location location; + QPoint crossPos; + QPoint penPos; + QPixmap saveUnder; + QTimer *timer; + int dx; + int dy; + bool showCross; +}; + +#endif // _WS_QWS_ + diff --git a/core/apps/calibrate/calibrate.pro b/core/apps/calibrate/calibrate.pro new file mode 100644 index 0000000..9769ea6 --- a/dev/null +++ b/core/apps/calibrate/calibrate.pro @@ -0,0 +1 @@ +# This is part of the taskbar diff --git a/core/apps/embeddedkonsole/.cvsignore b/core/apps/embeddedkonsole/.cvsignore new file mode 100644 index 0000000..6fe2396 --- a/dev/null +++ b/core/apps/embeddedkonsole/.cvsignore @@ -0,0 +1,2 @@ +moc_* +Makefile diff --git a/core/apps/embeddedkonsole/Makefile.in b/core/apps/embeddedkonsole/Makefile.in new file mode 100644 index 0000000..b858cd4 --- a/dev/null +++ b/core/apps/embeddedkonsole/Makefile.in @@ -0,0 +1,285 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = $(QPEDIR)/bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = embeddedkonsole +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = TEWidget.h \ + TEScreen.h \ + TECommon.h \ + TEHistory.h \ + TEmulation.h \ + TEmuVt102.h \ + session.h \ + keytrans.h \ + konsole.h \ + MyPty.h +SOURCES = TEScreen.cpp \ + TEWidget.cpp \ + TEHistory.cpp \ + TEmulation.cpp \ + TEmuVt102.cpp \ + session.cpp \ + keytrans.cpp \ + konsole.cpp \ + main.cpp \ + MyPty.cpp +OBJECTS = TEScreen.o \ + TEWidget.o \ + TEHistory.o \ + TEmulation.o \ + TEmuVt102.o \ + session.o \ + keytrans.o \ + konsole.o \ + main.o \ + MyPty.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = moc_TEWidget.cpp \ + moc_TEmulation.cpp \ + moc_TEmuVt102.cpp \ + moc_session.cpp \ + moc_konsole.cpp \ + moc_MyPty.cpp +OBJMOC = moc_TEWidget.o \ + moc_TEmulation.o \ + moc_TEmuVt102.o \ + moc_session.o \ + moc_konsole.o \ + moc_MyPty.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake embeddedkonsole.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES=embeddedkonsole + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +TEScreen.o: TEScreen.cpp \ + TEScreen.h \ + TECommon.h \ + TEHistory.h + +TEWidget.o: TEWidget.cpp \ + TEWidget.h \ + TECommon.h \ + session.h \ + MyPty.h \ + TEmuVt102.h \ + TEScreen.h \ + TEHistory.h \ + TEmulation.h \ + keytrans.h + +TEHistory.o: TEHistory.cpp \ + TEHistory.h \ + TECommon.h + +TEmulation.o: TEmulation.cpp \ + TEmulation.h \ + TEWidget.h \ + TECommon.h \ + TEScreen.h \ + TEHistory.h \ + keytrans.h + +TEmuVt102.o: TEmuVt102.cpp \ + TEmuVt102.h \ + TEWidget.h \ + TECommon.h \ + TEScreen.h \ + TEHistory.h \ + TEmulation.h \ + keytrans.h + +session.o: session.cpp \ + session.h \ + MyPty.h \ + TEWidget.h \ + TECommon.h \ + TEmuVt102.h \ + TEScreen.h \ + TEHistory.h \ + TEmulation.h \ + keytrans.h + +keytrans.o: keytrans.cpp \ + keytrans.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + default.keytab.h + +konsole.o: konsole.cpp \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/qpetoolbar.h \ + $(QPEDIR)/include/qpe/qpemenubar.h \ + konsole.h \ + MyPty.h \ + TEWidget.h \ + TECommon.h \ + TEmuVt102.h \ + TEScreen.h \ + TEHistory.h \ + TEmulation.h \ + keytrans.h \ + session.h + +main.o: main.cpp \ + konsole.h \ + MyPty.h \ + TEWidget.h \ + TECommon.h \ + TEmuVt102.h \ + TEScreen.h \ + TEHistory.h \ + TEmulation.h \ + keytrans.h \ + session.h \ + $(QPEDIR)/include/qpe/qpeapplication.h + +MyPty.o: MyPty.cpp \ + MyPty.h + +moc_TEWidget.o: moc_TEWidget.cpp \ + TEWidget.h \ + TECommon.h + +moc_TEmulation.o: moc_TEmulation.cpp \ + TEmulation.h \ + TEWidget.h \ + TECommon.h \ + TEScreen.h \ + TEHistory.h \ + keytrans.h + +moc_TEmuVt102.o: moc_TEmuVt102.cpp \ + TEmuVt102.h \ + TEWidget.h \ + TECommon.h \ + TEScreen.h \ + TEHistory.h \ + TEmulation.h \ + keytrans.h + +moc_session.o: moc_session.cpp \ + session.h \ + MyPty.h \ + TEWidget.h \ + TECommon.h \ + TEmuVt102.h \ + TEScreen.h \ + TEHistory.h \ + TEmulation.h \ + keytrans.h + +moc_konsole.o: moc_konsole.cpp \ + konsole.h \ + MyPty.h \ + TEWidget.h \ + TECommon.h \ + TEmuVt102.h \ + TEScreen.h \ + TEHistory.h \ + TEmulation.h \ + keytrans.h \ + session.h + +moc_MyPty.o: moc_MyPty.cpp \ + MyPty.h + +moc_TEWidget.cpp: TEWidget.h + $(MOC) TEWidget.h -o moc_TEWidget.cpp + +moc_TEmulation.cpp: TEmulation.h + $(MOC) TEmulation.h -o moc_TEmulation.cpp + +moc_TEmuVt102.cpp: TEmuVt102.h + $(MOC) TEmuVt102.h -o moc_TEmuVt102.cpp + +moc_session.cpp: session.h + $(MOC) session.h -o moc_session.cpp + +moc_konsole.cpp: konsole.h + $(MOC) konsole.h -o moc_konsole.cpp + +moc_MyPty.cpp: MyPty.h + $(MOC) MyPty.h -o moc_MyPty.cpp + + diff --git a/core/apps/embeddedkonsole/MyPty.cpp b/core/apps/embeddedkonsole/MyPty.cpp new file mode 100644 index 0000000..3622d48 --- a/dev/null +++ b/core/apps/embeddedkonsole/MyPty.cpp @@ -0,0 +1,279 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [MyPty.C] Pseudo Terminal Device */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +/* If you're compiling konsole on non-Linux platforms and find + problems that you can track down to this file, please have + a look into ../README.ports, too. +*/ + +/*! \file +*/ + +/*! \class TEPty + + \brief Ptys provide a pseudo terminal connection to a program. + + Although closely related to pipes, these pseudo terminal connections have + some ability, that makes it nessesary to uses them. Most importent, they + know about changing screen sizes and UNIX job control. + + Within the terminal emulation framework, this class represents the + host side of the terminal together with the connecting serial line. + + One can create many instances of this class within a program. + As a side effect of using this class, a signal(2) handler is + installed on SIGCHLD. + + \par FIXME + + [NOTE: much of the technical stuff below will be replaced by forkpty.] + + publish the SIGCHLD signal if not related to an instance. + + clearify TEPty::done vs. TEPty::~TEPty semantics. + check if pty is restartable via run after done. + + \par Pseudo terminals + + Pseudo terminals are a unique feature of UNIX, and always come in form of + pairs of devices (/dev/ptyXX and /dev/ttyXX), which are connected to each + other by the operating system. One may think of them as two serial devices + linked by a null-modem cable. Being based on devices the number of + simultanous instances of this class is (globally) limited by the number of + those device pairs, which is 256. + + Another technic are UNIX 98 PTY's. These are supported also, and prefered + over the (obsolete) predecessor. + + There's a sinister ioctl(2), signal(2) and job control stuff + nessesary to make everything work as it should. +*/ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_OPENPTY +#include +#endif + +#include "MyPty.h" + + +#undef VERBOSE_DEBUG + + +/* -------------------------------------------------------------------------- */ + +/*! + Informs the client program about the + actual size of the window. +*/ + +void MyPty::setSize(int lines, int columns) +{ + struct winsize wsize; + wsize.ws_row = (unsigned short)lines; + wsize.ws_col = (unsigned short)columns; + if(fd < 0) return; + ioctl(fd,TIOCSWINSZ,(char *)&wsize); +} + + +void MyPty::donePty() +{ + // This is code from the Qt DumbTerminal example + int status = 0; + + ::close(fd); + + if (cpid) { + kill(cpid, SIGHUP); + waitpid(cpid, &status, 0); + } + + emit done(status); +} + + +const char* MyPty::deviceName() +{ + return ttynam; +} + + +void MyPty::error() +{ + // This is code from the Qt DumbTerminal example + donePty(); +} + + +/*! + start the client program. +*/ +int MyPty::run(const char* cmd, QStrList &, const char*, int) +{ + // This is code from the Qt DumbTerminal example + cpid = fork(); + + if ( !cpid ) { + // child - exec shell on tty + for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL); + int ttyfd = open(ttynam, O_RDWR); + dup2(ttyfd, STDIN_FILENO); + dup2(ttyfd, STDOUT_FILENO); + dup2(ttyfd, STDERR_FILENO); + // should be done with tty, so close it + close(ttyfd); + static struct termios ttmode; + if ( setsid() < 0 ) + perror( "failed to set process group" ); +#if defined (TIOCSCTTY) + // grabbed from APUE by Stevens + ioctl(STDIN_FILENO, TIOCSCTTY, 0); +#endif + tcgetattr( STDIN_FILENO, &ttmode ); + ttmode.c_cc[VINTR] = 3; + ttmode.c_cc[VERASE] = 8; + tcsetattr( STDIN_FILENO, TCSANOW, &ttmode ); + setenv("TERM","vt100",1); + setenv("COLORTERM","0",1); + + if (getuid() == 0) { + char msg[] = "WARNING: You are running this shell as root!\n"; + write(ttyfd, msg, sizeof(msg)); + } + execl(cmd, cmd, 0); + + donePty(); + exit(-1); + } + + // parent - continue as a widget + QSocketNotifier* sn_r = new QSocketNotifier(fd,QSocketNotifier::Read,this); + QSocketNotifier* sn_e = new QSocketNotifier(fd,QSocketNotifier::Exception,this); + connect(sn_r,SIGNAL(activated(int)),this,SLOT(readPty())); + connect(sn_e,SIGNAL(activated(int)),this,SLOT(error())); + + return 0; +} + +int MyPty::openPty() +{ + // This is code from the Qt DumbTerminal example + int ptyfd = -1; + +#ifdef HAVE_OPENPTY + int ttyfd; + if ( openpty(&ptyfd,&ttyfd,ttynam,0,0) ) + ptyfd = -1; + else + close(ttyfd); // we open the ttynam ourselves. +#else + for (const char* c0 = "pqrstuvwxyzabcde"; ptyfd < 0 && *c0 != 0; c0++) { + for (const char* c1 = "0123456789abcdef"; ptyfd < 0 && *c1 != 0; c1++) { + sprintf(ptynam,"/dev/pty%c%c",*c0,*c1); + sprintf(ttynam,"/dev/tty%c%c",*c0,*c1); + if ((ptyfd = ::open(ptynam,O_RDWR)) >= 0) { + if (geteuid() != 0 && !access(ttynam,R_OK|W_OK) == 0) { + ::close(ptyfd); + ptyfd = -1; + } + } + } + } +#endif + + if ( ptyfd < 0 ) { + qApp->exit(1); + return -1; + } + + return ptyfd; +} + +/*! + Create an instance. +*/ +MyPty::MyPty() : cpid(0) +{ + fd = openPty(); +} + +/*! + Destructor. + Note that the related client program is not killed + (yet) when a instance is deleted. +*/ +MyPty::~MyPty() +{ + donePty(); +} + + +/*! sends len bytes through the line */ +void MyPty::send_bytes(const char* s, int len) +{ + +#ifdef VERBOSE_DEBUG + // verbose debug + printf("sending bytes:\n"); + for (int i = 0; i < len; i++) + printf("%c", s[i]); + printf("\n"); +#endif + + ::write(fd, s, len); +} + +/*! indicates that a block of data is received */ +void MyPty::readPty() +{ + char buf[4096]; + + int len = ::read( fd, buf, 4096 ); + + if (len == -1) + donePty(); + + if (len < 0) + return; + + emit block_in(buf,len); + +#ifdef VERBOSE_DEBUG + // verbose debug + printf("read bytes:\n"); + for (int i = 0; i < len; i++) + printf("%c", buf[i]); + printf("\n"); +#endif + +} + diff --git a/core/apps/embeddedkonsole/MyPty.h b/core/apps/embeddedkonsole/MyPty.h new file mode 100644 index 0000000..b2a5b58 --- a/dev/null +++ b/core/apps/embeddedkonsole/MyPty.h @@ -0,0 +1,88 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [MyPty.h] Pseudo Terminal Device */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +/*! \file +*/ + +#ifndef MY_PTY_H +#define MY_PTY_H + +#include +#include + + +class MyPty : public QObject +{ +Q_OBJECT + + public: + + MyPty(); + ~MyPty(); + + /*! + having a `run' separate from the constructor allows to make + the necessary connections to the signals and slots of the + instance before starting the execution of the client. + */ + int run(const char* pgm, QStrList & args, const char* term, int addutmp); + + public slots: + + void send_bytes(const char* s, int len); + void setSize(int lines, int columns); + void error(); + + signals: + + /*! + emitted when the client program terminates. + \param status the wait(2) status code of the terminated client program. + */ + void done(int status); + + /*! + emitted when a new block of data comes in. + \param s - the data + \param len - the length of the block + */ + void block_in(const char* s, int len); + + public: + + void send_byte(char s); +// void send_string(const char* s); + + const char* deviceName(); + + protected slots: + void readPty(); + void donePty(); + + private: + int openPty(); + + private: + + char ptynam[16]; // "/dev/ptyxx" | "/dev/ptmx" + char ttynam[16]; // "/dev/ttyxx" | "/dev/pts/########..." + int fd; + int cpid; +}; + +#endif diff --git a/core/apps/embeddedkonsole/TECommon.h b/core/apps/embeddedkonsole/TECommon.h new file mode 100644 index 0000000..261d51b --- a/dev/null +++ b/core/apps/embeddedkonsole/TECommon.h @@ -0,0 +1,114 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [TECommon.h] Common Definitions */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +/*! \file TECommon.h + \brief Definitions shared between TEScreen and TEWidget. +*/ + +#ifndef TECOMMON_H +#define TECOMMON_H + +#include + +#ifndef BOOL +typedef int BOOL; +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef UINT8 +typedef unsigned char UINT8; +#endif + +#ifndef UINT16 +typedef unsigned short UINT16; +#endif + +// Attributed Character Representations /////////////////////////////// + +// Colors + +#define BASE_COLORS (2+8) +#define INTENSITIES 2 +#define TABLE_COLORS (INTENSITIES*BASE_COLORS) + +#define DEFAULT_FORE_COLOR 0 +#define DEFAULT_BACK_COLOR 1 + +#define DEFAULT_RENDITION 0 +#define RE_BOLD (1 << 0) +#define RE_BLINK (1 << 1) +#define RE_UNDERLINE (1 << 2) +#define RE_REVERSE (1 << 3) // Screen only +#define RE_INTENSIVE (1 << 3) // Widget only + +/*! \class ca + * \brief a character with rendition attributes. +*/ + +class ca +{ +public: + inline ca(UINT16 _c = ' ', + UINT8 _f = DEFAULT_FORE_COLOR, + UINT8 _b = DEFAULT_BACK_COLOR, + UINT8 _r = DEFAULT_RENDITION) + : c(_c), f(_f), b(_b), r(_r) {} +public: + UINT16 c; // character + UINT8 f; // foreground color + UINT8 b; // background color + UINT8 r; // rendition +public: + friend BOOL operator == (ca a, ca b); + friend BOOL operator != (ca a, ca b); +}; + +inline BOOL operator == (ca a, ca b) +{ + return a.c == b.c && a.f == b.f && a.b == b.b && a.r == b.r; +} + +inline BOOL operator != (ca a, ca b) +{ + return a.c != b.c || a.f != b.f || a.b != b.b || a.r != b.r; +} + +/*! +*/ +struct ColorEntry +{ + ColorEntry(QColor c, bool tr, bool b) : color(c), transparent(tr), bold(b) {} + ColorEntry() : transparent(false), bold(false) {} // default constructors + void operator=(const ColorEntry& rhs) { + color = rhs.color; + transparent = rhs.transparent; + bold = rhs.bold; + } + QColor color; + bool transparent; // if used on bg + bool bold; // if used on fg +}; + +#endif // TECOMMON_H diff --git a/core/apps/embeddedkonsole/TEHistory.cpp b/core/apps/embeddedkonsole/TEHistory.cpp new file mode 100644 index 0000000..317ce57 --- a/dev/null +++ b/core/apps/embeddedkonsole/TEHistory.cpp @@ -0,0 +1,212 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [TEHistory.C] History Buffer */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +#include "TEHistory.h" +#include +#include +#include +#include +#include +#include + +#define HERE printf("%s(%d): here\n",__FILE__,__LINE__) + +/* + An arbitrary long scroll. + + One can modify the scroll only by adding either cells + or newlines, but access it randomly. + + The model is that of an arbitrary wide typewriter scroll + in that the scroll is a serie of lines and each line is + a serie of cells with no overwriting permitted. + + The implementation provides arbitrary length and numbers + of cells and line/column indexed read access to the scroll + at constant costs. + +FIXME: some complain about the history buffer comsuming the + memory of their machines. This problem is critical + since the history does not behave gracefully in cases + where the memory is used up completely. + + I put in a workaround that should handle it problem + now gracefully. I'm not satisfied with the solution. + +FIXME: Terminating the history is not properly indicated + in the menu. We should throw a signal. + +FIXME: There is noticable decrease in speed, also. Perhaps, + there whole feature needs to be revisited therefore. + Disadvantage of a more elaborated, say block-oriented + scheme with wrap around would be it's complexity. +*/ + +//FIXME: tempory replacement for tmpfile +// this is here one for debugging purpose. + +//#define tmpfile xTmpFile + +FILE* xTmpFile() +{ + static int fid = 0; + char fname[80]; + sprintf(fname,"TmpFile.%d",fid++); + return fopen(fname,"w"); +} + + +// History Buffer /////////////////////////////////////////// + +/* + A Row(X) data type which allows adding elements to the end. +*/ + +HistoryBuffer::HistoryBuffer() +{ + ion = -1; + length = 0; +} + +HistoryBuffer::~HistoryBuffer() +{ + setScroll(FALSE); +} + +void HistoryBuffer::setScroll(bool on) +{ + if (on == hasScroll()) return; + + if (on) + { + assert( ion < 0 ); + assert( length == 0); + FILE* tmp = tmpfile(); if (!tmp) { perror("konsole: cannot open temp file.\n"); return; } + ion = dup(fileno(tmp)); if (ion<0) perror("konsole: cannot dup temp file.\n"); + fclose(tmp); + } + else + { + assert( ion >= 0 ); + close(ion); + ion = -1; + length = 0; + } +} + +bool HistoryBuffer::hasScroll() +{ + return ion >= 0; +} + +void HistoryBuffer::add(const unsigned char* bytes, int len) +{ int rc; + assert(hasScroll()); + rc = lseek(ion,length,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::add.seek"); setScroll(FALSE); return; } + rc = write(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::add.write"); setScroll(FALSE); return; } + length += rc; +} + +void HistoryBuffer::get(unsigned char* bytes, int len, int loc) +{ int rc; + assert(hasScroll()); + if (loc < 0 || len < 0 || loc + len > length) + fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc); + rc = lseek(ion,loc,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::get.seek"); setScroll(FALSE); return; } + rc = read(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::get.read"); setScroll(FALSE); return; } +} + +int HistoryBuffer::len() +{ + return length; +} + +// History Scroll ////////////////////////////////////// + +/* + The history scroll makes a Row(Row(Cell)) from + two history buffers. The index buffer contains + start of line positions which refere to the cells + buffer. + + Note that index[0] addresses the second line + (line #1), while the first line (line #0) starts + at 0 in cells. +*/ + +HistoryScroll::HistoryScroll() +{ +} + +HistoryScroll::~HistoryScroll() +{ +} + +void HistoryScroll::setScroll(bool on) +{ + index.setScroll(on); + cells.setScroll(on); +} + +bool HistoryScroll::hasScroll() +{ + return index.hasScroll() && cells.hasScroll(); +} + +int HistoryScroll::getLines() +{ + if (!hasScroll()) return 0; + return index.len() / sizeof(int); +} + +int HistoryScroll::getLineLen(int lineno) +{ + if (!hasScroll()) return 0; + return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(ca); +} + +int HistoryScroll::startOfLine(int lineno) +{ + if (lineno <= 0) return 0; + if (!hasScroll()) return 0; + if (lineno <= getLines()) + { int res; + index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int)); + return res; + } + return cells.len(); +} + +void HistoryScroll::getCells(int lineno, int colno, int count, ca res[]) +{ + assert(hasScroll()); + cells.get((unsigned char*)res,count*sizeof(ca),startOfLine(lineno)+colno*sizeof(ca)); +} + +void HistoryScroll::addCells(ca text[], int count) +{ + if (!hasScroll()) return; + cells.add((unsigned char*)text,count*sizeof(ca)); +} + +void HistoryScroll::addLine() +{ + if (!hasScroll()) return; + int locn = cells.len(); + index.add((unsigned char*)&locn,sizeof(int)); +} diff --git a/core/apps/embeddedkonsole/TEHistory.h b/core/apps/embeddedkonsole/TEHistory.h new file mode 100644 index 0000000..8339ec6 --- a/dev/null +++ b/core/apps/embeddedkonsole/TEHistory.h @@ -0,0 +1,75 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [TEHistory.H] History Buffer */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +#ifndef TEHISTORY_H +#define TEHISTORY_H + +#include "TECommon.h" + +/* + An extendable tmpfile(1) based buffer. +*/ +class HistoryBuffer +{ +public: + HistoryBuffer(); + ~HistoryBuffer(); + +public: + void setScroll(bool on); + bool hasScroll(); + +public: + void add(const unsigned char* bytes, int len); + void get(unsigned char* bytes, int len, int loc); + int len(); + +private: + int ion; + int length; +}; + +class HistoryScroll +{ +public: + HistoryScroll(); + ~HistoryScroll(); + +public: + void setScroll(bool on); + bool hasScroll(); + +public: // access to history + int getLines(); + int getLineLen(int lineno); + void getCells(int lineno, int colno, int count, ca res[]); + +public: // backward compatibility (obsolete) + ca getCell(int lineno, int colno) { ca res; getCells(lineno,colno,1,&res); return res; } + +public: // adding lines. + void addCells(ca a[], int count); + void addLine(); + +private: + int startOfLine(int lineno); + HistoryBuffer index; // lines Row(int) + HistoryBuffer cells; // text Row(ca) +}; + +#endif // TEHISTORY_H diff --git a/core/apps/embeddedkonsole/TEScreen.cpp b/core/apps/embeddedkonsole/TEScreen.cpp new file mode 100644 index 0000000..a3d115d --- a/dev/null +++ b/core/apps/embeddedkonsole/TEScreen.cpp @@ -0,0 +1,1197 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [TEScreen.C] Screen Data Type */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +/*! \file +*/ + +/*! \class TEScreen + + \brief The image manipulated by the emulation. + + This class implements the operations of the terminal emulation framework. + It is a complete passive device, driven by the emulation decoder + (TEmuVT102). By this it forms in fact an ADT, that defines operations + on a rectangular image. + + It does neither know how to display its image nor about escape sequences. + It is further independent of the underlying toolkit. By this, one can even + use this module for an ordinary text surface. + + Since the operations are called by a specific emulation decoder, one may + collect their different operations here. + + The state manipulated by the operations is mainly kept in `image', though + it is a little more complex bejond this. See the header file of the class. + + \sa TEWidget \sa VT102Emulation +*/ + +#include +#include +#include +// #include + +#include +#include +#include + +#include "TEScreen.h" + +#define HERE printf("%s(%d): here\n",__FILE__,__LINE__) + +//FIXME: this is emulation specific. Use FALSE for xterm, TRUE for ANSI. +//FIXME: see if we can get this from terminfo. +#define BS_CLEARS FALSE + +#define loc(X,Y) ((Y)*columns+(X)) + +/*! creates a `TEScreen' of `lines' lines and `columns' columns. +*/ + +TEScreen::TEScreen(int lines, int columns) +{ + this->lines = lines; + this->columns = columns; + + image = (ca*) malloc(lines*columns*sizeof(ca)); + tabstops = NULL; initTabStops(); + + histCursor = 0; + + clearSelection(); + reset(); +} + +/*! Destructor +*/ + +TEScreen::~TEScreen() +{ + free(image); + if (tabstops) free(tabstops); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Normalized Screen Operations */ +/* */ +/* ------------------------------------------------------------------------- */ + +// Cursor Setting -------------------------------------------------------------- + +/*! \section Cursor + + The `cursor' is a location within the screen that is implicitely used in + many operations. The operations within this section allow to manipulate + the cursor explicitly and to obtain it's value. + + The position of the cursor is guarantied to be between (including) 0 and + `columns-1' and `lines-1'. +*/ + +/*! + Move the cursor up. + + The cursor will not be moved beyond the top margin. +*/ + +void TEScreen::cursorUp(int n) +//=CUU +{ + if (n == 0) n = 1; // Default + int stop = cuY < tmargin ? 0 : tmargin; + cuX = QMIN(columns-1,cuX); // nowrap! + cuY = QMAX(stop,cuY-n); +} + +/*! + Move the cursor down. + + The cursor will not be moved beyond the bottom margin. +*/ + +void TEScreen::cursorDown(int n) +//=CUD +{ + if (n == 0) n = 1; // Default + int stop = cuY > bmargin ? lines-1 : bmargin; + cuX = QMIN(columns-1,cuX); // nowrap! + cuY = QMIN(stop,cuY+n); +} + +/*! + Move the cursor left. + + The cursor will not move beyond the first column. +*/ + +void TEScreen::cursorLeft(int n) +//=CUB +{ + if (n == 0) n = 1; // Default + cuX = QMIN(columns-1,cuX); // nowrap! + cuX = QMAX(0,cuX-n); +} + +/*! + Move the cursor left. + + The cursor will not move beyond the rightmost column. +*/ + +void TEScreen::cursorRight(int n) +//=CUF +{ + if (n == 0) n = 1; // Default + cuX = QMIN(columns-1,cuX+n); +} + +/*! + Set top and bottom margin. +*/ + +void TEScreen::setMargins(int top, int bot) +//=STBM +{ + if (top == 0) top = 1; // Default + if (bot == 0) bot = lines; // Default + top = top - 1; // Adjust to internal lineno + bot = bot - 1; // Adjust to internal lineno + if ( !( 0 <= top && top < bot && bot < lines ) ) + { fprintf(stderr,"%s(%d) : setRegion(%d,%d) : bad range.\n", + __FILE__,__LINE__,top,bot); + return; // Default error action: ignore + } + tmargin = top; + bmargin = bot; + cuX = 0; + cuY = getMode(MODE_Origin) ? top : 0; +} + +/*! + Move the cursor down one line. + + If cursor is on bottom margin, the region between the + actual top and bottom margin is scrolled up instead. +*/ + +void TEScreen::index() +//=IND +{ + if (cuY == bmargin) + { + if (tmargin == 0 && bmargin == lines-1) addHistLine(); // hist.history + scrollUp(tmargin,1); + } + else if (cuY < lines-1) + cuY += 1; +} + +/*! + Move the cursor up one line. + + If cursor is on the top margin, the region between the + actual top and bottom margin is scrolled down instead. +*/ + +void TEScreen::reverseIndex() +//=RI +{ + if (cuY == tmargin) + scrollDown(tmargin,1); + else if (cuY > 0) + cuY -= 1; +} + +/*! + Move the cursor to the begin of the next line. + + If cursor is on bottom margin, the region between the + actual top and bottom margin is scrolled up. +*/ + +void TEScreen::NextLine() +//=NEL +{ + Return(); index(); +} + +// Line Editing ---------------------------------------------------------------- + +/*! \section inserting / deleting characters +*/ + +/*! erase `n' characters starting from (including) the cursor position. + + The line is filled in from the right with spaces. +*/ + +void TEScreen::eraseChars(int n) +{ + if (n == 0) n = 1; // Default + int p = QMAX(0,QMIN(cuX+n-1,columns-1)); + clearImage(loc(cuX,cuY),loc(p,cuY),' '); +} + +/*! delete `n' characters starting from (including) the cursor position. + + The line is filled in from the right with spaces. +*/ + +void TEScreen::deleteChars(int n) +{ + if (n == 0) n = 1; // Default + int p = QMAX(0,QMIN(cuX+n,columns-1)); + moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY)); + clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' '); +} + +/*! insert `n' spaces at the cursor position. + + The cursor is not moved by the operation. +*/ + +void TEScreen::insertChars(int n) +{ + if (n == 0) n = 1; // Default + int p = QMAX(0,QMIN(columns-1-n,columns-1)); + int q = QMAX(0,QMIN(cuX+n,columns-1)); + moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY)); + clearImage(loc(cuX,cuY),loc(q-1,cuY),' '); +} + +/*! delete `n' lines starting from (including) the cursor position. + + The cursor is not moved by the operation. +*/ + +void TEScreen::deleteLines(int n) +{ + if (n == 0) n = 1; // Default + scrollUp(cuY,n); +} + +/*! insert `n' lines at the cursor position. + + The cursor is not moved by the operation. +*/ + +void TEScreen::insertLines(int n) +{ + if (n == 0) n = 1; // Default + scrollDown(cuY,n); +} + +// Mode Operations ----------------------------------------------------------- + +/*! Set a specific mode. */ + +void TEScreen::setMode(int m) +{ + currParm.mode[m] = TRUE; + switch(m) + { + case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home + } +} + +/*! Reset a specific mode. */ + +void TEScreen::resetMode(int m) +{ + currParm.mode[m] = FALSE; + switch(m) + { + case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home + } +} + +/*! Save a specific mode. */ + +void TEScreen::saveMode(int m) +{ + saveParm.mode[m] = currParm.mode[m]; +} + +/*! Restore a specific mode. */ + +void TEScreen::restoreMode(int m) +{ + currParm.mode[m] = saveParm.mode[m]; +} + +//NOTE: this is a helper function +/*! Return the setting a specific mode. */ +BOOL TEScreen::getMode(int m) +{ + return currParm.mode[m]; +} + +/*! Save the cursor position and the rendition attribute settings. */ + +void TEScreen::saveCursor() +{ + sa_cuX = cuX; + sa_cuY = cuY; + sa_cu_re = cu_re; + sa_cu_fg = cu_fg; + sa_cu_bg = cu_bg; +} + +/*! Restore the cursor position and the rendition attribute settings. */ + +void TEScreen::restoreCursor() +{ + cuX = QMIN(sa_cuX,columns-1); + cuY = QMIN(sa_cuY,lines-1); + cu_re = sa_cu_re; + cu_fg = sa_cu_fg; + cu_bg = sa_cu_bg; + effectiveRendition(); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Screen Operations */ +/* */ +/* ------------------------------------------------------------------------- */ + +/*! Assing a new size to the screen. + + The topmost left position is maintained, while lower lines + or right hand side columns might be removed or filled with + spaces to fit the new size. + + The region setting is reset to the whole screen and the + tab positions reinitialized. +*/ + +void TEScreen::resizeImage(int new_lines, int new_columns) +{ + + if (cuY > new_lines-1) + { // attempt to preserve focus and lines + bmargin = lines-1; //FIXME: margin lost + for (int i = 0; i < cuY-(new_lines-1); i++) + { + addHistLine(); scrollUp(0,1); + } + } + + // make new image + ca* newimg = (ca*)malloc(new_lines*new_columns*sizeof(ca)); + + clearSelection(); + + // clear new image + for (int y = 0; y < new_lines; y++) + for (int x = 0; x < new_columns; x++) + { + newimg[y*new_columns+x].c = ' '; + newimg[y*new_columns+x].f = DEFAULT_FORE_COLOR; + newimg[y*new_columns+x].b = DEFAULT_BACK_COLOR; + newimg[y*new_columns+x].r = DEFAULT_RENDITION; + } + int cpy_lines = QMIN(new_lines, lines); + int cpy_columns = QMIN(new_columns,columns); + // copy to new image + for (int y = 0; y < cpy_lines; y++) + for (int x = 0; x < cpy_columns; x++) + { + newimg[y*new_columns+x].c = image[loc(x,y)].c; + newimg[y*new_columns+x].f = image[loc(x,y)].f; + newimg[y*new_columns+x].b = image[loc(x,y)].b; + newimg[y*new_columns+x].r = image[loc(x,y)].r; + } + free(image); + image = newimg; + lines = new_lines; + columns = new_columns; + cuX = QMIN(cuX,columns-1); + cuY = QMIN(cuY,lines-1); + + // FIXME: try to keep values, evtl. + tmargin=0; + bmargin=lines-1; + initTabStops(); + clearSelection(); +} + +/* + Clarifying rendition here and in TEWidget. + + currently, TEWidget's color table is + 0 1 2 .. 9 10 .. 17 + dft_fg, dft_bg, dim 0..7, intensive 0..7 + + cu_fg, cu_bg contain values 0..8; + - 0 = default color + - 1..8 = ansi specified color + + re_fg, re_bg contain values 0..17 + due to the TEWidget's color table + + rendition attributes are + + attr widget screen + -------------- ------ ------ + RE_UNDERLINE XX XX affects foreground only + RE_BLINK XX XX affects foreground only + RE_BOLD XX XX affects foreground only + RE_REVERSE -- XX + RE_TRANSPARENT XX -- affects background only + RE_INTENSIVE XX -- affects foreground only + + Note that RE_BOLD is used in both widget + and screen rendition. Since xterm/vt102 + is to poor to distinguish between bold + (which is a font attribute) and intensive + (which is a color attribute), we translate + this and RE_BOLD in falls eventually appart + into RE_BOLD and RE_INTENSIVE. +*/ + +void TEScreen::reverseRendition(ca* p) +{ UINT8 f = p->f; UINT8 b = p->b; + p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT; +} + +void TEScreen::effectiveRendition() +// calculate rendition +{ + ef_re = cu_re & (RE_UNDERLINE | RE_BLINK); + if (cu_re & RE_REVERSE) + { + ef_fg = cu_bg; + ef_bg = cu_fg; + } + else + { + ef_fg = cu_fg; + ef_bg = cu_bg; + } + if (cu_re & RE_BOLD) + { + if (ef_fg < BASE_COLORS) + ef_fg += BASE_COLORS; + else + ef_fg -= BASE_COLORS; + } +} + +/*! + returns the image. + + Get the size of the image by \sa getLines and \sa getColumns. + + NOTE that the image returned by this function must later be + freed. + +*/ + +ca* TEScreen::getCookedImage() +{ int x,y; + ca* merged = (ca*)malloc(lines*columns*sizeof(ca)); + ca dft(' ',DEFAULT_FORE_COLOR,DEFAULT_BACK_COLOR,DEFAULT_RENDITION); + + for (y = 0; (y < lines) && (y < (hist.getLines()-histCursor)); y++) + { + int len = QMIN(columns,hist.getLineLen(y+histCursor)); + int yp = y*columns; + int yq = (y+histCursor)*columns; + + hist.getCells(y+histCursor,0,len,merged+yp); + for (x = len; x < columns; x++) merged[yp+x] = dft; + for (x = 0; x < columns; x++) + { int p=x + yp; int q=x + yq; + if ( ( q >= sel_TL ) && ( q <= sel_BR ) ) + reverseRendition(&merged[p]); // for selection + } + } + if (lines >= hist.getLines()-histCursor) + { + for (y = (hist.getLines()-histCursor); y < lines ; y++) + { + int yp = y*columns; + int yq = (y+histCursor)*columns; + int yr = (y-hist.getLines()+histCursor)*columns; + for (x = 0; x < columns; x++) + { int p = x + yp; int q = x + yq; int r = x + yr; + merged[p] = image[r]; + if ( q >= sel_TL && q <= sel_BR ) + reverseRendition(&merged[p]); // for selection + } + + } + } + // evtl. inverse display + if (getMode(MODE_Screen)) + { int i,n = lines*columns; + for (i = 0; i < n; i++) + reverseRendition(&merged[i]); // for reverse display + } + if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines)) // cursor visible + reverseRendition(&merged[loc(cuX,cuY+(hist.getLines()-histCursor))]); + return merged; +} + + +/*! +*/ + +void TEScreen::reset() +{ + setMode(MODE_Wrap ); saveMode(MODE_Wrap ); // wrap at end of margin + resetMode(MODE_Origin); saveMode(MODE_Origin); // position refere to [1,1] + resetMode(MODE_Insert); saveMode(MODE_Insert); // overstroke + setMode(MODE_Cursor); // cursor visible + resetMode(MODE_Screen); // screen not inverse + resetMode(MODE_NewLine); + + tmargin=0; + bmargin=lines-1; + + setDefaultRendition(); + saveCursor(); + + clear(); +} + +/*! Clear the entire screen and home the cursor. +*/ + +void TEScreen::clear() +{ + clearEntireScreen(); + home(); +} + +/*! Moves the cursor left one column. +*/ + +void TEScreen::BackSpace() +{ + cuX = QMAX(0,cuX-1); + if (BS_CLEARS) image[loc(cuX,cuY)].c = ' '; +} + +/*! +*/ + +void TEScreen::Tabulate() +{ + // note that TAB is a format effector (does not write ' '); + cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1); +} + +void TEScreen::clearTabStops() +{ + for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE; +} + +void TEScreen::changeTabStop(bool set) +{ + if (cuX >= columns) return; + tabstops[cuX] = set; +} + +void TEScreen::initTabStops() +{ + if (tabstops) free(tabstops); + tabstops = (bool*)malloc(columns*sizeof(bool)); + // Arrg! The 1st tabstop has to be one longer than the other. + // i.e. the kids start counting from 0 instead of 1. + // Other programs might behave correctly. Be aware. + for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0); +} + +/*! + This behaves either as IND (Screen::Index) or as NEL (Screen::NextLine) + depending on the NewLine Mode (LNM). This mode also + affects the key sequence returned for newline ([CR]LF). +*/ + +void TEScreen::NewLine() +{ + if (getMode(MODE_NewLine)) Return(); + index(); +} + +/*! put `c' literally onto the screen at the current cursor position. + + VT100 uses the convention to produce an automatic newline (am) + with the *first* character that would fall onto the next line (xenl). +*/ + +void TEScreen::checkSelection(int from, int to) +{ + if (sel_begin == -1) return; + int scr_TL = loc(0, hist.getLines()); + //Clear entire selection if it overlaps region [from, to] + if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) ) + { + clearSelection(); + } +} + +void TEScreen::ShowCharacter(unsigned short c) +{ + // Note that VT100 does wrapping BEFORE putting the character. + // This has impact on the assumption of valid cursor positions. + // We indicate the fact that a newline has to be triggered by + // putting the cursor one right to the last column of the screen. + + if (cuX >= columns) + { + if (getMode(MODE_Wrap)) NextLine(); else cuX = columns-1; + } + + if (getMode(MODE_Insert)) insertChars(1); + + int i = loc(cuX,cuY); + + checkSelection(i, i); // check if selection is still valid. + + image[i].c = c; + image[i].f = ef_fg; + image[i].b = ef_bg; + image[i].r = ef_re; + + cuX += 1; +} + +// Region commands ------------------------------------------------------------- + + +/*! scroll up `n' lines within current region. + The `n' new lines are cleared. + \sa setRegion \sa scrollDown +*/ + +void TEScreen::scrollUp(int from, int n) +{ + if (n <= 0 || from + n > bmargin) return; + //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds. + moveImage(loc(0,from),loc(0,from+n),loc(columns-1,bmargin)); + clearImage(loc(0,bmargin-n+1),loc(columns-1,bmargin),' '); +} + +/*! scroll down `n' lines within current region. + The `n' new lines are cleared. + \sa setRegion \sa scrollUp +*/ + +void TEScreen::scrollDown(int from, int n) +{ +//FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds. + if (n <= 0) return; + if (from > bmargin) return; + if (from + n > bmargin) n = bmargin - from; + moveImage(loc(0,from+n),loc(0,from),loc(columns-1,bmargin-n)); + clearImage(loc(0,from),loc(columns-1,from+n-1),' '); +} + +/*! position the cursor to a specific line and column. */ +void TEScreen::setCursorYX(int y, int x) +{ + setCursorY(y); setCursorX(x); +} + +/*! Set the cursor to x-th line. */ + +void TEScreen::setCursorX(int x) +{ + if (x == 0) x = 1; // Default + x -= 1; // Adjust + cuX = QMAX(0,QMIN(columns-1, x)); +} + +/*! Set the cursor to y-th line. */ + +void TEScreen::setCursorY(int y) +{ + if (y == 0) y = 1; // Default + y -= 1; // Adjust + cuY = QMAX(0,QMIN(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) )); +} + +/*! set cursor to the `left upper' corner of the screen (1,1). +*/ + +void TEScreen::home() +{ + cuX = 0; + cuY = 0; +} + +/*! set cursor to the begin of the current line. +*/ + +void TEScreen::Return() +{ + cuX = 0; +} + +/*! returns the current cursor columns. +*/ + +int TEScreen::getCursorX() +{ + return cuX; +} + +/*! returns the current cursor line. +*/ + +int TEScreen::getCursorY() +{ + return cuY; +} + +// Erasing --------------------------------------------------------------------- + +/*! \section Erasing + + This group of operations erase parts of the screen contents by filling + it with spaces colored due to the current rendition settings. + + Althought the cursor position is involved in most of these operations, + it is never modified by them. +*/ + +/*! fill screen between (including) `loca' and `loce' with spaces. + + This is an internal helper functions. The parameter types are internal + addresses of within the screen image and make use of the way how the + screen matrix is mapped to the image vector. +*/ + +void TEScreen::clearImage(int loca, int loce, char c) +{ int i; + int scr_TL=loc(0,hist.getLines()); + //FIXME: check positions + + //Clear entire selection if it overlaps region to be moved... + if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) ) + { + clearSelection(); + } + for (i = loca; i <= loce; i++) + { + image[i].c = c; + image[i].f = ef_fg; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi + image[i].b = ef_bg; //DEFAULT_BACK_COLOR; // many have different + image[i].r = ef_re; //DEFAULT_RENDITION; // ideas here. + } +} + +/*! move image between (including) `loca' and `loce' to 'dst'. + + This is an internal helper functions. The parameter types are internal + addresses of within the screen image and make use of the way how the + screen matrix is mapped to the image vector. +*/ + +void TEScreen::moveImage(int dst, int loca, int loce) +{ +//FIXME: check positions + if (loce < loca) { + // kdDebug() << "WARNING!!! call to TEScreen:moveImage with loce < loca!" << endl; + return; + } + memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(ca)); +} + +/*! clear from (including) current cursor position to end of screen. +*/ + +void TEScreen::clearToEndOfScreen() +{ + clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' '); +} + +/*! clear from begin of screen to (including) current cursor position. +*/ + +void TEScreen::clearToBeginOfScreen() +{ + clearImage(loc(0,0),loc(cuX,cuY),' '); +} + +/*! clear the entire screen. +*/ + +void TEScreen::clearEntireScreen() +{ + clearImage(loc(0,0),loc(columns-1,lines-1),' '); +} + +/*! fill screen with 'E' + This is to aid screen alignment +*/ + +void TEScreen::helpAlign() +{ + clearImage(loc(0,0),loc(columns-1,lines-1),'E'); +} + +/*! clear from (including) current cursor position to end of current cursor line. +*/ + +void TEScreen::clearToEndOfLine() +{ + clearImage(loc(cuX,cuY),loc(columns-1,cuY),' '); +} + +/*! clear from begin of current cursor line to (including) current cursor position. +*/ + +void TEScreen::clearToBeginOfLine() +{ + clearImage(loc(0,cuY),loc(cuX,cuY),' '); +} + +/*! clears entire current cursor line +*/ + +void TEScreen::clearEntireLine() +{ + clearImage(loc(0,cuY),loc(columns-1,cuY),' '); +} + +// Rendition ------------------------------------------------------------------ + +/*! + set rendition mode +*/ + +void TEScreen::setRendition(int re) +{ + cu_re |= re; + effectiveRendition(); +} + +/*! + reset rendition mode +*/ + +void TEScreen::resetRendition(int re) +{ + cu_re &= ~re; + effectiveRendition(); +} + +/*! +*/ + +void TEScreen::setDefaultRendition() +{ + setForeColorToDefault(); + setBackColorToDefault(); + cu_re = DEFAULT_RENDITION; + effectiveRendition(); +} + +/*! +*/ + +void TEScreen::setForeColor(int fgcolor) +{ + cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2); + effectiveRendition(); +} + +/*! +*/ + +void TEScreen::setBackColor(int bgcolor) +{ + cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2); + effectiveRendition(); +} + +/*! +*/ + +void TEScreen::setBackColorToDefault() +{ + cu_bg = DEFAULT_BACK_COLOR; + effectiveRendition(); +} + +/*! +*/ + +void TEScreen::setForeColorToDefault() +{ + cu_fg = DEFAULT_FORE_COLOR; + effectiveRendition(); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Marking & Selection */ +/* */ +/* ------------------------------------------------------------------------- */ + +void TEScreen::clearSelection() +{ + sel_BR = -1; + sel_TL = -1; + sel_begin = -1; +} + +void TEScreen::setSelBeginXY(const int x, const int y) +{ + sel_begin = loc(x,y+histCursor) ; + sel_BR = sel_begin; + sel_TL = sel_begin; +} + +void TEScreen::setSelExtentXY(const int x, const int y) +{ + if (sel_begin == -1) return; + int l = loc(x,y + histCursor); + + if (l < sel_begin) + { + sel_TL = l; + sel_BR = sel_begin; + } + else + { + /* FIXME, HACK to correct for x too far to the right... */ + if (( x == columns )|| (x == 0)) l--; + + sel_TL = sel_begin; + sel_BR = l; + } +} + +QString TEScreen::getSelText(const BOOL preserve_line_breaks) +{ + if (sel_begin == -1) + return QString::null; // Selection got clear while selecting. + + int *m; // buffer to fill. + int s, d; // source index, dest. index. + int hist_BR = loc(0, hist.getLines()); + int hY = sel_TL / columns; + int hX = sel_TL % columns; + int eol; // end of line + + s = sel_TL; // tracks copy in source. + + // allocate buffer for maximum + // possible size... + d = (sel_BR - sel_TL) / columns + 1; + m = new int[d * (columns + 1) + 2]; + d = 0; + + while (s <= sel_BR) + { + if (s < hist_BR) + { // get lines from hist.history + // buffer. + eol = hist.getLineLen(hY); + + if ((hY == (sel_BR / columns)) && + (eol >= (sel_BR % columns))) + { + eol = sel_BR % columns + 1; + } + + while (hX < eol) + { + m[d++] = hist.getCell(hY, hX++).c; + s++; + } + + if (s <= sel_BR) + { + // The line break handling + // It's different from the screen + // image case! + if (eol % columns == 0) + { + // That's either a completely filled + // line or an empty line + if (eol == 0) + { + m[d++] = '\n'; + } + else + { + // We have a full line. + // FIXME: How can we handle newlines + // at this position?! + } + } + else if ((eol + 1) % columns == 0) + { + // FIXME: We don't know if this was a + // space at the last position or a + // short line!! + m[d++] = ' '; + } + else + { + // We have a short line here. Put a + // newline or a space into the + // buffer. + m[d++] = preserve_line_breaks ? '\n' : ' '; + } + } + + hY++; + hX = 0; + s = hY * columns; + } + else + { // or from screen image. + eol = (s / columns + 1) * columns - 1; + + if (eol < sel_BR) + { + while ((eol > s) && + isspace(image[eol - hist_BR].c)) + { + eol--; + } + } + else + { + eol = sel_BR; + } + + while (s <= eol) + { + m[d++] = image[s++ - hist_BR].c; + } + + if (eol < sel_BR) + { + // eol processing see below ... + if ((eol + 1) % columns == 0) + { + if (image[eol - hist_BR].c == ' ') + { + m[d++] = ' '; + } + } + else + { + m[d++] = ((preserve_line_breaks || + ((eol % columns) == 0)) ? + '\n' : ' '); + } + } + + s = (eol / columns + 1) * columns; + } + } + + QChar* qc = new QChar[d]; + + for (int i = 0; i < d; i++) + { + qc[i] = m[i]; + } + + QString res(qc, d); + + delete m; + delete qc; + + return res; +} +/* above ... end of line processing for selection -- psilva +cases: + +1) (eol+1)%columns == 0 --> the whole line is filled. + If the last char is a space, insert (preserve) space. otherwise + leave the text alone, so that words that are broken by linewrap + are preserved. + +FIXME: + * this suppresses \n for command output that is + sized to the exact column width of the screen. + +2) eol%columns == 0 --> blank line. + insert a \n unconditionally. + Do it either you would because you are in preserve_line_break mode, + or because it's an ASCII paragraph delimiter, so even when + not preserving line_breaks, you want to preserve paragraph breaks. + +3) else --> partially filled line + insert a \n in preserve line break mode, else a space + The space prevents concatenation of the last word of one + line with the first of the next. + +*/ + +void TEScreen::addHistLine() +{ + assert(hasScroll() || histCursor == 0); + + // add to hist buffer + // we have to take care about scrolling, too... + + if (hasScroll()) + { ca dft; + + int end = columns-1; + while (end >= 0 && image[end] == dft) + end -= 1; + + hist.addCells(image,end+1); + hist.addLine(); + + // adjust history cursor + histCursor += (hist.getLines()-1 == histCursor); + } + + if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround +} + +void TEScreen::setHistCursor(int cursor) +{ + histCursor = cursor; //FIXME:rangecheck +} + +int TEScreen::getHistCursor() +{ + return histCursor; +} + +int TEScreen::getHistLines() +{ + return hist.getLines(); +} + +void TEScreen::setScroll(bool on) +{ + histCursor = 0; + clearSelection(); + hist.setScroll(on); +} + +bool TEScreen::hasScroll() +{ + return hist.hasScroll(); +} diff --git a/core/apps/embeddedkonsole/TEScreen.h b/core/apps/embeddedkonsole/TEScreen.h new file mode 100644 index 0000000..ba47ee5 --- a/dev/null +++ b/core/apps/embeddedkonsole/TEScreen.h @@ -0,0 +1,259 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [te_screen.h] Screen Data Type */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +#ifndef TESCREEN_H +#define TESCREEN_H + +/*! \file +*/ + +#include "TECommon.h" +#include "TEHistory.h" + +#define MODE_Origin 0 +#define MODE_Wrap 1 +#define MODE_Insert 2 +#define MODE_Screen 3 +#define MODE_Cursor 4 +#define MODE_NewLine 5 +#define MODES_SCREEN 6 + +/*! +*/ +struct ScreenParm +{ + int mode[MODES_SCREEN]; +}; + + +class TEScreen +{ +public: + TEScreen(int lines, int columns); + ~TEScreen(); + +public: // these are all `Screen' operations + // + // VT100/2 Operations ------------------ + // + // Cursor Movement + // + void cursorUp (int n); + void cursorDown (int n); + void cursorLeft (int n); + void cursorRight (int n); + void setCursorY (int y); + void setCursorX (int x); + void setCursorYX (int y, int x); + void setMargins (int t, int b); + // + // Cursor Movement with Scrolling + // + void NewLine (); + void NextLine (); + void index (); + void reverseIndex(); + // + void Return (); + void BackSpace (); + void Tabulate (); + // + // Editing + // + void eraseChars (int n); + void deleteChars (int n); + void insertChars (int n); + void deleteLines (int n); + void insertLines (int n); + // + // ------------------------------------- + // + void clearTabStops(); + void changeTabStop(bool set); + // + void resetMode (int n); + void setMode (int n); + void saveMode (int n); + void restoreMode (int n); + // + void saveCursor (); + void restoreCursor(); + // + // ------------------------------------- + // + void clearEntireScreen(); + void clearToEndOfScreen(); + void clearToBeginOfScreen(); + // + void clearEntireLine(); + void clearToEndOfLine(); + void clearToBeginOfLine(); + // + void helpAlign (); + // + // ------------------------------------- + // + void setRendition (int rendition); + void resetRendition(int rendition); + void setForeColor (int fgcolor); + void setBackColor (int bgcolor); + // + void setDefaultRendition(); + void setForeColorToDefault(); + void setBackColorToDefault(); + // + // ------------------------------------- + // + BOOL getMode (int n); + // + // only for report cursor position + // + int getCursorX(); + int getCursorY(); + // + // ------------------------------------- + // + void clear(); + void home(); + void reset(); + // + void ShowCharacter(unsigned short c); + // + void resizeImage(int new_lines, int new_columns); + // + ca* getCookedImage(); + + /*! return the number of lines. */ + int getLines() { return lines; } + /*! return the number of columns. */ + int getColumns() { return columns; } + + /*! set the position of the history cursor. */ + void setHistCursor(int cursor); + /*! return the position of the history cursor. */ + int getHistCursor(); + + int getHistLines (); + void setScroll(bool on); + bool hasScroll(); + + // + // Selection + // + void setSelBeginXY(const int x, const int y); + void setSelExtentXY(const int x, const int y); + void clearSelection(); + QString getSelText(const BOOL preserve_line_breaks); + + void checkSelection(int from, int to); + +private: // helper + + void clearImage(int loca, int loce, char c); + void moveImage(int dst, int loca, int loce); + + void scrollUp(int from, int i); + void scrollDown(int from, int i); + + void addHistLine(); + + void initTabStops(); + + void effectiveRendition(); + void reverseRendition(ca* p); + +private: + + /* + The state of the screen is more complex as one would + expect first. The screem does really do part of the + emulation providing state informations in form of modes, + margins, tabulators, cursor etc. + + Even more unexpected are variables to save and restore + parts of the state. + */ + + // screen image ---------------- + + int lines; + int columns; + ca *image; // [lines][columns] + + // history buffer --------------- + + int histCursor; // display position relative to start of the history buffer + HistoryScroll hist; + + // cursor location + + int cuX; + int cuY; + + // cursor color and rendition info + + UINT8 cu_fg; // foreground + UINT8 cu_bg; // background + UINT8 cu_re; // rendition + + // margins ---------------- + + int tmargin; // top margin + int bmargin; // bottom margin + + // states ---------------- + + ScreenParm currParm; + + // ---------------------------- + + bool* tabstops; + + // selection ------------------- + + int sel_begin; // The first location selected. + int sel_TL; // TopLeft Location. + int sel_BR; // Bottom Right Location. + + // effective colors and rendition ------------ + + UINT8 ef_fg; // These are derived from + UINT8 ef_bg; // the cu_* variables above + UINT8 ef_re; // to speed up operation + + // + // save cursor, rendition & states ------------ + // + + // cursor location + + int sa_cuX; + int sa_cuY; + + // rendition info + + UINT8 sa_cu_re; + UINT8 sa_cu_fg; + UINT8 sa_cu_bg; + + // modes + + ScreenParm saveParm; +}; + +#endif // TESCREEN_H diff --git a/core/apps/embeddedkonsole/TEWidget.cpp b/core/apps/embeddedkonsole/TEWidget.cpp new file mode 100644 index 0000000..dc83998 --- a/dev/null +++ b/core/apps/embeddedkonsole/TEWidget.cpp @@ -0,0 +1,1243 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* [TEWidget.C] Terminal Emulation Widget */ +/* */ +/* ------------------------------------------------------------------------ */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* ------------------------------------------------------------------------ */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +/*! \class TEWidget + + \brief Visible screen contents + + This class is responsible to map the `image' of a terminal emulation to the + display. All the dependency of the emulation to a specific GUI or toolkit is + localized here. Further, this widget has no knowledge about being part of an + emulation, it simply work within the terminal emulation framework by exposing + size and key events and by being ordered to show a new image. + +
    +
  • The internal image has the size of the widget (evtl. rounded up) +
  • The external image used in setImage can have any size. +
  • (internally) the external image is simply copied to the internal + when a setImage happens. During a resizeEvent no painting is done + a paintEvent is expected to follow anyway. +
+ + \sa TEScreen \sa Emulation +*/ + +/* FIXME: + - 'image' may also be used uninitialized (it isn't in fact) in resizeEvent + - 'font_a' not used in mouse events + - add destructor +*/ + +/* TODO + - evtl. be sensitive to `paletteChange' while using default colors. + - set different 'rounding' styles? I.e. have a mode to show clipped chars? +*/ + +// #include "config.h" +#include "TEWidget.h" +#include "session.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +// #include "TEWidget.moc" +//#include +//#include +//#include +//#include +//#include + +#define HERE printf("%s(%d): %s\n",__FILE__,__LINE__,__FUNCTION__) +#define HCNT(Name) // { static int cnt = 1; printf("%s(%d): %s %d\n",__FILE__,__LINE__,Name,cnt++); } + +#define loc(X,Y) ((Y)*columns+(X)) + +//FIXME: the rim should normally be 1, 0 only when running in full screen mode. +#define rimX 0 // left/right rim width +#define rimY 0 // top/bottom rim high + +#define SCRWIDTH 16 // width of the scrollbar + +#define yMouseScroll 1 +// scroll increment used when dragging selection at top/bottom of window. + +/* ------------------------------------------------------------------------- */ +/* */ +/* Colors */ +/* */ +/* ------------------------------------------------------------------------- */ + +//FIXME: the default color table is in session.C now. +// We need a way to get rid of this one, here. +static const ColorEntry base_color_table[TABLE_COLORS] = +// The following are almost IBM standard color codes, with some slight +// gamma correction for the dim colors to compensate for bright X screens. +// It contains the 8 ansiterm/xterm colors in 2 intensities. +{ + // Fixme: could add faint colors here, also. + // normal + ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 1, 0 ), // Dfore, Dback + ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red + ColorEntry(QColor(0x18,0xB2,0x18), 0, 0 ), ColorEntry( QColor(0xB2,0x68,0x18), 0, 0 ), // Green, Yellow + ColorEntry(QColor(0x18,0x18,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), // Blue, Magenta + ColorEntry(QColor(0x18,0xB2,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 0, 0 ), // Cyan, White + // intensiv + ColorEntry(QColor(0x00,0x00,0x00), 0, 1 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 1, 0 ), + ColorEntry(QColor(0x68,0x68,0x68), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0x54), 0, 0 ), + ColorEntry(QColor(0x54,0xFF,0x54), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0x54), 0, 0 ), + ColorEntry(QColor(0x54,0x54,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0xFF), 0, 0 ), + ColorEntry(QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 ) +}; + +/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb) + + Code 0 1 2 3 4 5 6 7 + ----------- ------- ------- ------- ------- ------- ------- ------- ------- + ANSI (bgr) Black Red Green Yellow Blue Magenta Cyan White + IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White +*/ + +QColor TEWidget::getDefaultBackColor() +{ + return color_table[DEFAULT_BACK_COLOR].color; +} + +const ColorEntry* TEWidget::getColorTable() const +{ + return color_table; +} + +const QPixmap *TEWidget::backgroundPixmap() +{ + static QPixmap *bg = new QPixmap("~/qpim/main/pics/faded_bg.xpm"); + const QPixmap *pm = bg; + return pm; +} + +void TEWidget::setColorTable(const ColorEntry table[]) +{ + for (int i = 0; i < TABLE_COLORS; i++) color_table[i] = table[i]; + + const QPixmap* pm = backgroundPixmap(); + if (!pm) setBackgroundColor(color_table[DEFAULT_BACK_COLOR].color); + update(); +} + +//FIXME: add backgroundPixmapChanged. + +/* ------------------------------------------------------------------------- */ +/* */ +/* Font */ +/* */ +/* ------------------------------------------------------------------------- */ + +/* + The VT100 has 32 special graphical characters. The usual vt100 extended + xterm fonts have these at 0x00..0x1f. + + QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals + come in here as proper unicode characters. + + We treat non-iso10646 fonts as VT100 extended and do the requiered mapping + from unicode to 0x00..0x1f. The remaining translation is then left to the + QCodec. +*/ + +// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i. + +unsigned short vt100_graphics[32] = +{ // 0/8 1/9 2/10 3/11 4/12 5/13 6/14 7/15 + 0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, + 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, + 0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534, + 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7 +}; + +static QChar vt100extended(QChar c) +{ + switch (c.unicode()) + { + case 0x25c6 : return 1; + case 0x2592 : return 2; + case 0x2409 : return 3; + case 0x240c : return 4; + case 0x240d : return 5; + case 0x240a : return 6; + case 0x00b0 : return 7; + case 0x00b1 : return 8; + case 0x2424 : return 9; + case 0x240b : return 10; + case 0x2518 : return 11; + case 0x2510 : return 12; + case 0x250c : return 13; + case 0x2514 : return 14; + case 0x253c : return 15; + case 0xf800 : return 16; + case 0xf801 : return 17; + case 0x2500 : return 18; + case 0xf803 : return 19; + case 0xf804 : return 20; + case 0x251c : return 21; + case 0x2524 : return 22; + case 0x2534 : return 23; + case 0x252c : return 24; + case 0x2502 : return 25; + case 0x2264 : return 26; + case 0x2265 : return 27; + case 0x03c0 : return 28; + case 0x2260 : return 29; + case 0x00a3 : return 30; + case 0x00b7 : return 31; + } + return c; +} + +static QChar identicalMap(QChar c) +{ + return c; +} + +void TEWidget::fontChange(const QFont &) +{ + QFontMetrics fm(font()); + font_h = fm.height(); + font_w = fm.maxWidth(); + font_a = fm.ascent(); +//printf("font_h: %d\n",font_h); +//printf("font_w: %d\n",font_w); +//printf("font_a: %d\n",font_a); +//printf("charset: %s\n",QFont::encodingName(font().charSet()).ascii()); +//printf("rawname: %s\n",font().rawName().ascii()); + fontMap = +#if QT_VERSION < 300 + strcmp(QFont::encodingName(font().charSet()).ascii(),"iso10646") + ? vt100extended + : +#endif + identicalMap; + propagateSize(); + update(); +} + +void TEWidget::setVTFont(const QFont& f) +{ + QFrame::setFont(f); +} + +QFont TEWidget::getVTFont() +{ + return font(); +} + +void TEWidget::setFont(const QFont &) +{ + // ignore font change request if not coming from konsole itself +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Constructor / Destructor */ +/* */ +/* ------------------------------------------------------------------------- */ + +TEWidget::TEWidget(QWidget *parent, const char *name) : QFrame(parent,name) +{ +#ifndef QT_NO_CLIPBOARD + cb = QApplication::clipboard(); + QObject::connect( (QObject*)cb, SIGNAL(dataChanged()), + this, SLOT(onClearSelection()) ); +#endif + + scrollbar = new QScrollBar(this); + scrollbar->setCursor( arrowCursor ); + connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int))); + scrollLoc = SCRNONE; + + blinkT = new QTimer(this); + connect(blinkT, SIGNAL(timeout()), this, SLOT(blinkEvent())); + // blinking = FALSE; + blinking = TRUE; + + resizing = FALSE; + actSel = 0; + image = 0; + lines = 1; + columns = 1; + font_w = 1; + font_h = 1; + font_a = 1; + word_selection_mode = FALSE; + + setMouseMarks(TRUE); + setVTFont( QFont("fixed") ); + setColorTable(base_color_table); // init color table + + qApp->installEventFilter( this ); //FIXME: see below +// KCursor::setAutoHideCursor( this, true ); + + // Init DnD //////////////////////////////////////////////////////////////// + currentSession = NULL; +// setAcceptDrops(true); // attempt +// m_drop = new QPopupMenu(this); +// m_drop->insertItem( QString("Paste"), 0); +// m_drop->insertItem( QString("cd"), 1); +// connect(m_drop, SIGNAL(activated(int)), SLOT(drop_menu_activated(int))); + + // we need focus so that the auto-hide cursor feature works + setFocus(); + setFocusPolicy( WheelFocus ); +} + +//FIXME: make proper destructor +// Here's a start (David) +TEWidget::~TEWidget() +{ + qApp->removeEventFilter( this ); + if (image) free(image); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Display Operations */ +/* */ +/* ------------------------------------------------------------------------- */ + +/*! + attributed string draw primitive +*/ + +void TEWidget::drawAttrStr(QPainter &paint, QRect rect, + QString& str, ca attr, BOOL pm, BOOL clear) +{ + if (pm && color_table[attr.b].transparent) + { + paint.setBackgroundMode( TransparentMode ); + if (clear) erase(rect); + } + else + { + if (blinking) + paint.fillRect(rect, color_table[attr.b].color); + else + { + paint.setBackgroundMode( OpaqueMode ); + paint.setBackgroundColor( color_table[attr.b].color ); + } + } + + if (color_table[attr.f].bold) + paint.setPen(QColor( 0x8F, 0x00, 0x00 )); + else + paint.setPen(color_table[attr.f].color); + + paint.drawText(rect.x(),rect.y()+font_a, str); + + if (attr.r & RE_UNDERLINE) + paint.drawLine(rect.left(), rect.y()+font_a+1, rect.right(),rect.y()+font_a+1 ); +} + +/*! + The image can only be set completely. + + The size of the new image may or may not match the size of the widget. +*/ + +void TEWidget::setImage(const ca* const newimg, int lines, int columns) +{ int y,x,len; + const QPixmap* pm = backgroundPixmap(); + QPainter paint; + setUpdatesEnabled(FALSE); + paint.begin( this ); +HCNT("setImage"); + + QPoint tL = contentsRect().topLeft(); + int tLx = tL.x(); + int tLy = tL.y(); + hasBlinker = FALSE; + + int cf = -1; // undefined + int cb = -1; // undefined + int cr = -1; // undefined + + int lins = QMIN(this->lines, QMAX(0,lines )); + int cols = QMIN(this->columns,QMAX(0,columns)); + QChar *disstrU = new QChar[cols]; + +//{ static int cnt = 0; printf("setImage %d\n",cnt++); } + for (y = 0; y < lins; y++) + { + const ca* lcl = &image[y*this->columns]; + const ca* const ext = &newimg[y*columns]; + if (!resizing) // not while resizing, we're expecting a paintEvent + for (x = 0; x < cols; x++) + { + hasBlinker |= (ext[x].r & RE_BLINK); + if (ext[x] != lcl[x]) + { + cr = ext[x].r; + cb = ext[x].b; + if (ext[x].f != cf) cf = ext[x].f; + int lln = cols - x; + disstrU[0] = fontMap(ext[x+0].c); + for (len = 1; len < lln; len++) + { + if (ext[x+len].f != cf || ext[x+len].b != cb || ext[x+len].r != cr || + ext[x+len] == lcl[x+len] ) + break; + disstrU[len] = fontMap(ext[x+len].c); + } + QString unistr(disstrU,len); + drawAttrStr(paint, + QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h), + unistr, ext[x], pm != NULL, true); + x += len - 1; + } + } + // finally, make `image' become `newimg'. + memcpy((void*)lcl,(const void*)ext,cols*sizeof(ca)); + } + drawFrame( &paint ); + paint.end(); + setUpdatesEnabled(TRUE); + if ( hasBlinker && !blinkT->isActive()) blinkT->start(1000); // 1000 ms + if (!hasBlinker && blinkT->isActive()) { blinkT->stop(); blinking = FALSE; } + delete [] disstrU; +} + +// paint Event //////////////////////////////////////////////////// + +/*! + The difference of this routine vs. the `setImage' is, + that the drawing does not include a difference analysis + between the old and the new image. Instead, the internal + image is used and the painting bound by the PaintEvent box. +*/ + +void TEWidget::paintEvent( QPaintEvent* pe ) +{ + +//{ static int cnt = 0; printf("paint %d\n",cnt++); } + const QPixmap* pm = backgroundPixmap(); + QPainter paint; + setUpdatesEnabled(FALSE); + paint.begin( this ); + paint.setBackgroundMode( TransparentMode ); +HCNT("paintEvent"); + + // Note that the actual widget size can be slightly larger + // that the image (the size is truncated towards the smaller + // number of characters in `resizeEvent'. The paint rectangle + // can thus be larger than the image, but less then the size + // of one character. + + QRect rect = pe->rect().intersect(contentsRect()); + + QPoint tL = contentsRect().topLeft(); + int tLx = tL.x(); + int tLy = tL.y(); + + int lux = QMIN(columns-1, QMAX(0,(rect.left() - tLx - blX ) / font_w)); + int luy = QMIN(lines-1, QMAX(0,(rect.top() - tLy - bY ) / font_h)); + int rlx = QMIN(columns-1, QMAX(0,(rect.right() - tLx - blX ) / font_w)); + int rly = QMIN(lines-1, QMAX(0,(rect.bottom() - tLy - bY ) / font_h)); + + /* + printf("paintEvent: %d..%d, %d..%d (%d..%d, %d..%d)\n",lux,rlx,luy,rly, + rect.left(), rect.right(), rect.top(), rect.bottom()); + */ + + // if (pm != NULL && color_table[image->b].transparent) + // erase(rect); + // BL: I have no idea why we need this, and it breaks the refresh. + + QChar *disstrU = new QChar[columns]; + for (int y = luy; y <= rly; y++) + for (int x = lux; x <= rlx; x++) + { + int len = 1; + disstrU[0] = fontMap(image[loc(x,y)].c); + int cf = image[loc(x,y)].f; + int cb = image[loc(x,y)].b; + int cr = image[loc(x,y)].r; + while (x+len <= rlx && + image[loc(x+len,y)].f == cf && + image[loc(x+len,y)].b == cb && + image[loc(x+len,y)].r == cr ) + { + disstrU[len] = fontMap(image[loc(x+len,y)].c); + len += 1; + } + QString unistr(disstrU,len); + drawAttrStr(paint, + QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h), + unistr, image[loc(x,y)], pm != NULL, false); + x += len - 1; + } + delete [] disstrU; + drawFrame( &paint ); + paint.end(); + setUpdatesEnabled(TRUE); +} + +void TEWidget::blinkEvent() +{ + blinking = !blinking; + repaint(FALSE); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Resizing */ +/* */ +/* ------------------------------------------------------------------------- */ + +void TEWidget::resizeEvent(QResizeEvent* ev) +{ + //printf("resize: %d,%d\n",ev->size().width(),ev->size().height()); + //printf("approx: %d,%d\n",ev->size().width()/font_w,ev->size().height()/font_h); + //printf("leaves: %d,%d\n",ev->size().width()%font_w,ev->size().height()%font_h); + //printf("curren: %d,%d\n",width(),height()); +HCNT("resizeEvent"); + + // see comment in `paintEvent' concerning the rounding. + //FIXME: could make a routine here; check width(),height() + assert(ev->size().width() == width()); + assert(ev->size().height() == height()); + + propagateSize(); +} + +void TEWidget::propagateSize() +{ + ca* oldimg = image; + int oldlin = lines; + int oldcol = columns; + makeImage(); + // we copy the old image to reduce flicker + int lins = QMIN(oldlin,lines); + int cols = QMIN(oldcol,columns); + if (oldimg) + { + for (int lin = 0; lin < lins; lin++) + memcpy((void*)&image[columns*lin], + (void*)&oldimg[oldcol*lin],cols*sizeof(ca)); + free(oldimg); //FIXME: try new,delete + } + else + clearImage(); + + //NOTE: control flows from the back through the chest right into the eye. + // `emu' will call back via `setImage'. + + resizing = TRUE; + emit changedImageSizeSignal(lines, columns); // expose resizeEvent + resizing = FALSE; +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Scrollbar */ +/* */ +/* ------------------------------------------------------------------------- */ + +void TEWidget::scrollChanged(int) +{ + emit changedHistoryCursor(scrollbar->value()); //expose +} + +void TEWidget::setScroll(int cursor, int slines) +{ + disconnect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int))); + scrollbar->setRange(0,slines); + scrollbar->setSteps(1,lines); + scrollbar->setValue(cursor); + connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int))); +} + +void TEWidget::setScrollbarLocation(int loc) +{ + if (scrollLoc == loc) return; // quickly + scrollLoc = loc; + propagateSize(); + update(); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Mouse */ +/* */ +/* ------------------------------------------------------------------------- */ + +/*! + Three different operations can be performed using the mouse, and the + routines in this section serve all of them: + + 1) The press/release events are exposed to the application + 2) Marking (press and move left button) and Pasting (press middle button) + 3) The right mouse button is used from the configuration menu + + NOTE: During the marking process we attempt to keep the cursor within + the bounds of the text as being displayed by setting the mouse position + whenever the mouse has left the text area. + + Two reasons to do so: + 1) QT does not allow the `grabMouse' to confine-to the TEWidget. + Thus a `XGrapPointer' would have to be used instead. + 2) Even if so, this would not help too much, since the text area + of the TEWidget is normally not identical with it's bounds. + + The disadvantage of the current handling is, that the mouse can visibly + leave the bounds of the widget and is then moved back. Because of the + current construction, and the reasons mentioned above, we cannot do better + without changing the overall construction. +*/ + +/*! +*/ + +void TEWidget::mousePressEvent(QMouseEvent* ev) +{ +//printf("press [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button()); + if ( !contentsRect().contains(ev->pos()) ) return; + QPoint tL = contentsRect().topLeft(); + int tLx = tL.x(); + int tLy = tL.y(); + + word_selection_mode = FALSE; + +//printf("press top left [%d,%d] by=%d\n",tLx,tLy, bY); + if ( ev->button() == LeftButton) + { + QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h); + + if ( ev->state() & ControlButton ) preserve_line_breaks = FALSE ; + + if (mouse_marks || (ev->state() & ShiftButton)) + { + emit clearSelectionSignal(); + iPntSel = pntSel = pos; + actSel = 1; // left mouse button pressed but nothing selected yet. + grabMouse( /*crossCursor*/ ); // handle with care! + } + else + { + emit mouseSignal( 0, pos.x() + 1, pos.y() + 1 ); // left button + } + } + if ( ev->button() == MidButton ) + { + emitSelection(); + } + if ( ev->button() == RightButton ) // Configure + { + emit configureRequest( this, ev->state()&(ShiftButton|ControlButton), ev->x(), ev->y() ); + } +} + +void TEWidget::mouseMoveEvent(QMouseEvent* ev) +{ + // for auto-hiding the cursor, we need mouseTracking + if (ev->state() == NoButton ) return; + + if (actSel == 0) return; + + // don't extend selection while pasting + if (ev->state() & MidButton) return; + + //if ( !contentsRect().contains(ev->pos()) ) return; + QPoint tL = contentsRect().topLeft(); + int tLx = tL.x(); + int tLy = tL.y(); + int scroll = scrollbar->value(); + + // we're in the process of moving the mouse with the left button pressed + // the mouse cursor will kept catched within the bounds of the text in + // this widget. + + // Adjust position within text area bounds. See FIXME above. + QPoint pos = ev->pos(); + if ( pos.x() < tLx+blX ) pos.setX( tLx+blX ); + if ( pos.x() > tLx+blX+columns*font_w-1 ) pos.setX( tLx+blX+columns*font_w ); + if ( pos.y() < tLy+bY ) pos.setY( tLy+bY ); + if ( pos.y() > tLy+bY+lines*font_h-1 ) pos.setY( tLy+bY+lines*font_h-1 ); + // check if we produce a mouse move event by this + if ( pos != ev->pos() ) cursor().setPos(mapToGlobal(pos)); + + if ( pos.y() == tLy+bY+lines*font_h-1 ) + { + scrollbar->setValue(scrollbar->value()+yMouseScroll); // scrollforward + } + if ( pos.y() == tLy+bY ) + { + scrollbar->setValue(scrollbar->value()-yMouseScroll); // scrollback + } + + QPoint here = QPoint((pos.x()-tLx-blX)/font_w,(pos.y()-tLy-bY)/font_h); + QPoint ohere; + bool swapping = FALSE; + + if ( word_selection_mode ) + { + // Extend to word boundaries + int i; + int selClass; + + bool left_not_right = ( here.y() < iPntSel.y() || + here.y() == iPntSel.y() && here.x() < iPntSel.x() ); + bool old_left_not_right = ( pntSel.y() < iPntSel.y() || + pntSel.y() == iPntSel.y() && pntSel.x() < iPntSel.x() ); + swapping = left_not_right != old_left_not_right; + + // Find left (left_not_right ? from here : from start) + QPoint left = left_not_right ? here : iPntSel; + i = loc(left.x(),left.y()); + selClass = charClass(image[i].c); + while ( left.x() > 0 && charClass(image[i-1].c) == selClass ) + { i--; left.rx()--; } + + // Find left (left_not_right ? from start : from here) + QPoint right = left_not_right ? iPntSel : here; + i = loc(right.x(),right.y()); + selClass = charClass(image[i].c); + while ( right.x() < columns-1 && charClass(image[i+1].c) == selClass ) + { i++; right.rx()++; } + + // Pick which is start (ohere) and which is extension (here) + if ( left_not_right ) + { + here = left; ohere = right; + } + else + { + here = right; ohere = left; + } + } + + if (here == pntSel && scroll == scrollbar->value()) return; // not moved + + if ( word_selection_mode ) { + if ( actSel < 2 || swapping ) { + emit beginSelectionSignal( ohere.x(), ohere.y() ); + } + } else if ( actSel < 2 ) { + emit beginSelectionSignal( pntSel.x(), pntSel.y() ); + } + + actSel = 2; // within selection + pntSel = here; + emit extendSelectionSignal( here.x(), here.y() ); +} + +void TEWidget::mouseReleaseEvent(QMouseEvent* ev) +{ +//printf("release [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button()); + if ( ev->button() == LeftButton) + { + if ( actSel > 1 ) emit endSelectionSignal(preserve_line_breaks); + preserve_line_breaks = TRUE; + actSel = 0; + + //FIXME: emits a release event even if the mouse is + // outside the range. The procedure used in `mouseMoveEvent' + // applies here, too. + + QPoint tL = contentsRect().topLeft(); + int tLx = tL.x(); + int tLy = tL.y(); + + if (!mouse_marks && !(ev->state() & ShiftButton)) + emit mouseSignal( 3, // release + (ev->x()-tLx-blX)/font_w + 1, + (ev->y()-tLy-bY)/font_h + 1 ); + releaseMouse(); + } +} + +void TEWidget::mouseDoubleClickEvent(QMouseEvent* ev) +{ + if ( ev->button() != LeftButton) return; + + QPoint tL = contentsRect().topLeft(); + int tLx = tL.x(); + int tLy = tL.y(); + QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h); + + // pass on double click as two clicks. + if (!mouse_marks && !(ev->state() & ShiftButton)) + { + emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button + emit mouseSignal( 3, pos.x()+1, pos.y()+1 ); // release + emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button + return; + } + + + emit clearSelectionSignal(); + QPoint bgnSel = pos; + QPoint endSel = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h); + int i = loc(bgnSel.x(),bgnSel.y()); + iPntSel = bgnSel; + + word_selection_mode = TRUE; + + // find word boundaries... + int selClass = charClass(image[i].c); + { + // set the start... + int x = bgnSel.x(); + while ( x > 0 && charClass(image[i-1].c) == selClass ) + { i--; x--; } + bgnSel.setX(x); + emit beginSelectionSignal( bgnSel.x(), bgnSel.y() ); + + // set the end... + i = loc( endSel.x(), endSel.y() ); + x = endSel.x(); + while( x < columns-1 && charClass(image[i+1].c) == selClass ) + { i++; x++ ; } + endSel.setX(x); + actSel = 2; // within selection + emit extendSelectionSignal( endSel.x(), endSel.y() ); + emit endSelectionSignal(preserve_line_breaks); + preserve_line_breaks = TRUE; + } +} + +void TEWidget::focusInEvent( QFocusEvent * ) +{ + // do nothing, to prevent repainting +} + + +void TEWidget::focusOutEvent( QFocusEvent * ) +{ + // do nothing, to prevent repainting +} + +bool TEWidget::focusNextPrevChild( bool next ) +{ + if (next) + return false; // This disables changing the active part in konqueror + // when pressing Tab + return QFrame::focusNextPrevChild( next ); +} + + +int TEWidget::charClass(char ch) const +{ + // This might seem like overkill, but imagine if ch was a Unicode + // character (Qt 2.0 QChar) - it might then be sensible to separate + // the different language ranges, etc. + + if ( isspace(ch) ) return ' '; + + static const char *word_characters = ":@-./_~"; + if ( isalnum(ch) || strchr(word_characters, ch) ) + return 'a'; + + // Everything else is weird + return 1; +} + +void TEWidget::setMouseMarks(bool on) +{ + mouse_marks = on; + setCursor( mouse_marks ? ibeamCursor : arrowCursor ); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Clipboard */ +/* */ +/* ------------------------------------------------------------------------- */ + +#undef KeyPress + +void TEWidget::emitSelection() +// Paste Clipboard by simulating keypress events +{ +#ifndef QT_NO_CLIPBOARD + QString text = QApplication::clipboard()->text(); + if ( ! text.isNull() ) + { + text.replace(QRegExp("\n"), "\r"); + QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text); + emit keyPressedSignal(&e); // expose as a big fat keypress event + emit clearSelectionSignal(); + } +#endif +} + +void TEWidget::emitText(QString text) +{ + QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text); + emit keyPressedSignal(&e); // expose as a big fat keypress event +} + +void TEWidget::pasteClipboard( ) +{ + emitSelection(); +} + +void TEWidget::setSelection(const QString& t) +{ +#ifndef QT_NO_CLIPBOARD + // Disconnect signal while WE set the clipboard + QObject *cb = QApplication::clipboard(); + QObject::disconnect( cb, SIGNAL(dataChanged()), + this, SLOT(onClearSelection()) ); + + QApplication::clipboard()->setText(t); + + QObject::connect( cb, SIGNAL(dataChanged()), + this, SLOT(onClearSelection()) ); +#endif +} + +void TEWidget::onClearSelection() +{ + emit clearSelectionSignal(); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Keyboard */ +/* */ +/* ------------------------------------------------------------------------- */ + +//FIXME: an `eventFilter' has been installed instead of a `keyPressEvent' +// due to a bug in `QT' or the ignorance of the author to prevent +// repaint events being emitted to the screen whenever one leaves +// or reenters the screen to/from another application. +// +// Troll says one needs to change focusInEvent() and focusOutEvent(), +// which would also let you have an in-focus cursor and an out-focus +// cursor like xterm does. + +// for the auto-hide cursor feature, I added empty focusInEvent() and +// focusOutEvent() so that update() isn't called. +// For auto-hide, we need to get keypress-events, but we only get them when +// we have focus. + +void TEWidget::doScroll(int lines) +{ + scrollbar->setValue(scrollbar->value()+lines); +} + +bool TEWidget::eventFilter( QObject *obj, QEvent *e ) +{ + if ( (e->type() == QEvent::Accel || + e->type() == QEvent::AccelAvailable ) && qApp->focusWidget() == this ) + { + static_cast( e )->ignore(); + return true; + } + if ( obj != this /* when embedded */ && obj != parent() /* when standalone */ ) + return FALSE; // not us + if ( e->type() == QEvent::Wheel) + { + QApplication::sendEvent(scrollbar, e); + } + +#ifdef FAKE_CTRL_AND_ALT + static bool control = FALSE; + static bool alt = FALSE; + // Has a keyboard with no CTRL and ALT keys, but we fake it: + bool dele=FALSE; + if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease ) { + QKeyEvent* ke = (QKeyEvent*)e; + bool keydown = e->type() == QEvent::KeyPress || ke->isAutoRepeat(); + switch (ke->key()) { + case Key_F9: // let this be "Control" + control = keydown; + e = new QKeyEvent(QEvent::KeyPress, Key_Control, 0, ke->state()); + dele=TRUE; + break; + case Key_F13: // let this be "Alt" + alt = keydown; + e = new QKeyEvent(QEvent::KeyPress, Key_Alt, 0, ke->state()); + dele=TRUE; + break; + default: + if ( control ) { + int a = toupper(ke->ascii())-64; + if ( a >= 0 && a < ' ' ) { + e = new QKeyEvent(e->type(), ke->key(), + a, ke->state()|ControlButton, QChar(a,0)); + dele=TRUE; + } + } + if ( alt ) { + e = new QKeyEvent(e->type(), ke->key(), + ke->ascii(), ke->state()|AltButton, ke->text()); + dele=TRUE; + } + } + } +#endif + + if ( e->type() == QEvent::KeyPress ) + { + QKeyEvent* ke = (QKeyEvent*)e; + + actSel=0; // Key stroke implies a screen update, so TEWidget won't + // know where the current selection is. + + emit keyPressedSignal(ke); // expose + ke->accept(); +#ifdef FAKE_CTRL_AND_ALT + if ( dele ) delete e; +#endif + return true; // stop the event + } + if ( e->type() == QEvent::Enter ) + { + QObject::disconnect( (QObject*)cb, SIGNAL(dataChanged()), + this, SLOT(onClearSelection()) ); + } + if ( e->type() == QEvent::Leave ) + { + QObject::connect( (QObject*)cb, SIGNAL(dataChanged()), + this, SLOT(onClearSelection()) ); + } + return QFrame::eventFilter( obj, e ); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Frame */ +/* */ +/* ------------------------------------------------------------------------- */ + +void TEWidget::frameChanged() +{ + propagateSize(); + update(); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Sound */ +/* */ +/* ------------------------------------------------------------------------- */ + +void TEWidget::Bell() +{ + QApplication::beep(); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Auxiluary */ +/* */ +/* ------------------------------------------------------------------------- */ + +void TEWidget::clearImage() +// initialize the image +// for internal use only +{ + for (int y = 0; y < lines; y++) + for (int x = 0; x < columns; x++) + { + image[loc(x,y)].c = 0xff; //' '; + image[loc(x,y)].f = 0xff; //DEFAULT_FORE_COLOR; + image[loc(x,y)].b = 0xff; //DEFAULT_BACK_COLOR; + image[loc(x,y)].r = 0xff; //DEFAULT_RENDITION; + } +} + +// Create Image /////////////////////////////////////////////////////// + +void TEWidget::calcGeometry() +{ + //FIXME: set rimX == rimY == 0 when running in full screen mode. + + scrollbar->resize(QApplication::style().scrollBarExtent().width(), + contentsRect().height()); + switch(scrollLoc) + { + case SCRNONE : + columns = ( contentsRect().width() - 2 * rimX ) / font_w; + blX = (contentsRect().width() - (columns*font_w) ) / 2; + brX = blX; + scrollbar->hide(); + break; + case SCRLEFT : + columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w; + brX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2; + blX = brX + scrollbar->width(); + scrollbar->move(contentsRect().topLeft()); + scrollbar->show(); + break; + case SCRRIGHT: + columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w; + blX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2; + brX = blX; + scrollbar->move(contentsRect().topRight() - QPoint(scrollbar->width()-1,0)); + scrollbar->show(); + break; + } + //FIXME: support 'rounding' styles + lines = ( contentsRect().height() - 2 * rimY ) / font_h; + bY = (contentsRect().height() - (lines *font_h)) / 2; +} + +void TEWidget::makeImage() +//FIXME: rename 'calcGeometry? +{ + calcGeometry(); + image = (ca*) malloc(lines*columns*sizeof(ca)); + clearImage(); +} + +// calculate the needed size +QSize TEWidget::calcSize(int cols, int lins) const +{ + int frw = width() - contentsRect().width(); + int frh = height() - contentsRect().height(); + int scw = (scrollLoc==SCRNONE?0:scrollbar->width()); + return QSize( font_w*cols + 2*rimX + frw + scw, font_h*lins + 2*rimY + frh ); +} + +QSize TEWidget::sizeHint() const +{ + return size(); +} + +void TEWidget::styleChange(QStyle &) +{ + propagateSize(); +} + +#ifndef QT_NO_DRAGANDDROP + +/* --------------------------------------------------------------------- */ +/* */ +/* Drag & Drop */ +/* */ +/* --------------------------------------------------------------------- */ + + +void TEWidget::dragEnterEvent(QDragEnterEvent* e) +{ + e->accept(QTextDrag::canDecode(e) || + QUriDrag::canDecode(e)); +} + +void TEWidget::dropEvent(QDropEvent* event) +{ + // The current behaviour when url(s) are dropped is + // * if there is only ONE url and if it's a LOCAL one, ask for paste or cd + // * in all other cases, just paste + // (for non-local ones, or for a list of URLs, 'cd' is nonsense) + QStrList strlist; + int file_count = 0; + dropText = ""; + bool bPopup = true; + + if(QUriDrag::decode(event, strlist)) { + if (strlist.count()) { + for(const char* p = strlist.first(); p; p = strlist.next()) { + if(file_count++ > 0) { + dropText += " "; + bPopup = false; // more than one file, don't popup + } + +/* + KURL url(p); + if (url.isLocalFile()) { + dropText += url.path(); // local URL : remove protocol + } + else { + dropText += url.prettyURL(); + bPopup = false; // a non-local file, don't popup + } +*/ + + } + + if (bPopup) + // m_drop->popup(pos() + event->pos()); + m_drop->popup(mapToGlobal(event->pos())); + else + { + if (currentSession) { + currentSession->getEmulation()->sendString(dropText.local8Bit()); + } +// kdDebug() << "Drop:" << dropText.local8Bit() << "\n"; + } + } + } + else if(QTextDrag::decode(event, dropText)) { +// kdDebug() << "Drop:" << dropText.local8Bit() << "\n"; + if (currentSession) { + currentSession->getEmulation()->sendString(dropText.local8Bit()); + } + // Paste it + } +} +#endif + + +void TEWidget::drop_menu_activated(int item) +{ +#ifndef QT_NO_DRAGANDDROP + switch (item) + { + case 0: // paste + currentSession->getEmulation()->sendString(dropText.local8Bit()); +// KWM::activate((Window)this->winId()); + break; + case 1: // cd ... + currentSession->getEmulation()->sendString("cd "); + struct stat statbuf; + if ( ::stat( QFile::encodeName( dropText ), &statbuf ) == 0 ) + { + if ( !S_ISDIR(statbuf.st_mode) ) + { +/* + KURL url; + url.setPath( dropText ); + dropText = url.directory( true, false ); // remove filename +*/ + } + } + dropText.replace(QRegExp(" "), "\\ "); // escape spaces + currentSession->getEmulation()->sendString(dropText.local8Bit()); + currentSession->getEmulation()->sendString("\n"); +// KWM::activate((Window)this->winId()); + break; + } +#endif +} + diff --git a/core/apps/embeddedkonsole/TEWidget.h b/core/apps/embeddedkonsole/TEWidget.h new file mode 100644 index 0000000..3f9f4ae --- a/dev/null +++ b/core/apps/embeddedkonsole/TEWidget.h @@ -0,0 +1,202 @@ +/* ----------------------------------------------------------------------- */ +/* */ +/* [te_widget.h] Terminal Emulation Widget */ +/* */ +/* ----------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* ----------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +#ifndef TE_WIDGET_H +#define TE_WIDGET_H + +#include +#include +#include +#include +#include +#include + +#include + +#include "TECommon.h" + +extern unsigned short vt100_graphics[32]; + +class TESession; + +// class Konsole; + +class TEWidget : public QFrame +// a widget representing attributed text +{ Q_OBJECT + +// friend class Konsole; + +public: + + TEWidget(QWidget *parent=0, const char *name=0); + virtual ~TEWidget(); + +public: + + QColor getDefaultBackColor(); + + const ColorEntry* getColorTable() const; + void setColorTable(const ColorEntry table[]); + + void setScrollbarLocation(int loc); + enum { SCRNONE=0, SCRLEFT=1, SCRRIGHT=2 }; + + void setScroll(int cursor, int lines); + void doScroll(int lines); + + void emitSelection(); + +public: + + void setImage(const ca* const newimg, int lines, int columns); + + int Lines() { return lines; } + int Columns() { return columns; } + + void calcGeometry(); + void propagateSize(); + QSize calcSize(int cols, int lins) const; + + QSize sizeHint() const; + +public: + + void Bell(); + void emitText(QString text); + void pasteClipboard(); + +signals: + + void keyPressedSignal(QKeyEvent *e); + void mouseSignal(int cb, int cx, int cy); + void changedImageSizeSignal(int lines, int columns); + void changedHistoryCursor(int value); + void configureRequest( TEWidget*, int state, int x, int y ); + + void clearSelectionSignal(); + void beginSelectionSignal( const int x, const int y ); + void extendSelectionSignal( const int x, const int y ); + void endSelectionSignal(const BOOL preserve_line_breaks); + + +protected: + + virtual void styleChange( QStyle& ); + + bool eventFilter( QObject *, QEvent * ); + + void drawAttrStr(QPainter &paint, QRect rect, + QString& str, ca attr, BOOL pm, BOOL clear); + void paintEvent( QPaintEvent * ); + + void resizeEvent(QResizeEvent*); + + void fontChange(const QFont &font); + void frameChanged(); + + void mouseDoubleClickEvent(QMouseEvent* ev); + void mousePressEvent( QMouseEvent* ); + void mouseReleaseEvent( QMouseEvent* ); + void mouseMoveEvent( QMouseEvent* ); + + void focusInEvent( QFocusEvent * ); + void focusOutEvent( QFocusEvent * ); + bool focusNextPrevChild( bool next ); + +#ifndef QT_NO_DRAGANDDROP + // Dnd + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); +#endif + + virtual int charClass(char) const; + + void clearImage(); + +public: + const QPixmap *backgroundPixmap(); + + void setSelection(const QString &t); + + virtual void setFont(const QFont &); + void setVTFont(const QFont &); + QFont getVTFont(); + + void setMouseMarks(bool on); + +public slots: + + void onClearSelection(); + +protected slots: + + void scrollChanged(int value); + void blinkEvent(); + +private: + + QChar (*fontMap)(QChar); // possible vt100 font extention + + bool fixed_font; // has fixed pitch + int font_h; // height + int font_w; // width + int font_a; // ascend + + int blX; // actual offset (left) + int brX; // actual offset (right) + int bY; // actual offset + + int lines; + int columns; + ca *image; // [lines][columns] + + ColorEntry color_table[TABLE_COLORS]; + + BOOL resizing; + bool mouse_marks; + + void makeImage(); + + QPoint iPntSel; // initial selection point + QPoint pntSel; // current selection point + int actSel; // selection state + BOOL word_selection_mode; + BOOL preserve_line_breaks; + + QClipboard* cb; + QScrollBar* scrollbar; + int scrollLoc; + +//#define SCRNONE 0 +//#define SCRLEFT 1 +//#define SCRRIGHT 2 + + BOOL blinking; // hide text in paintEvent + BOOL hasBlinker; // has characters to blink + QTimer* blinkT; // active when hasBlinker + QPopupMenu* m_drop; + QString dropText; + public: + // current session in this widget + TESession *currentSession; +private slots: + void drop_menu_activated(int item); +}; + +#endif // TE_WIDGET_H diff --git a/core/apps/embeddedkonsole/TEmuVt102.cpp b/core/apps/embeddedkonsole/TEmuVt102.cpp new file mode 100644 index 0000000..752c49f --- a/dev/null +++ b/core/apps/embeddedkonsole/TEmuVt102.cpp @@ -0,0 +1,991 @@ +/* ------------------------------------------------------------------------- */ +/* */ +/* [TEmuVt102.C] VT102 Terminal Emulation */ +/* */ +/* ------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* ------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +/*! \class TEmuVt102 + + \brief Actual Emulation for Konsole + + \sa TEWidget \sa TEScreen +*/ + +#include "TEmuVt102.h" +#include "TEWidget.h" +#include "TEScreen.h" +#include "keytrans.h" + +#include +#include +#include +#include + + +/* VT102 Terminal Emulation + + This class puts together the screens, the pty and the widget to a + complete terminal emulation. Beside combining it's componentes, it + handles the emulations's protocol. + + This module consists of the following sections: + + - Constructor/Destructor + - Incoming Bytes Event pipeline + - Outgoing Bytes + - Mouse Events + - Keyboard Events + - Modes and Charset State + - Diagnostics +*/ + + +/* ------------------------------------------------------------------------- */ +/* */ +/* Constructor / Destructor */ +/* */ +/* ------------------------------------------------------------------------- */ + +/* + Nothing really intesting happens here. +*/ + +/*! +*/ + +TEmuVt102::TEmuVt102(TEWidget* gui) : TEmulation(gui) +{ + QObject::connect(gui,SIGNAL(mouseSignal(int,int,int)), + this,SLOT(onMouse(int,int,int))); + initTokenizer(); + reset(); +} + +/*! +*/ + +TEmuVt102::~TEmuVt102() +{ +} + +/*! +*/ + +void TEmuVt102::reset() +{ + resetToken(); + resetModes(); + resetCharset(0); screen[0]->reset(); + resetCharset(1); screen[0]->reset(); + setCodec(0); + setKeytrans("linux.keytab"); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Processing the incoming byte stream */ +/* */ +/* ------------------------------------------------------------------------- */ + +/* Incoming Bytes Event pipeline + + This section deals with decoding the incoming character stream. + Decoding means here, that the stream is first seperated into `tokens' + which are then mapped to a `meaning' provided as operations by the + `TEScreen' class or by the emulation class itself. + + The pipeline proceeds as follows: + + - Tokenizing the ESC codes (onRcvChar) + - VT100 code page translation of plain characters (applyCharset) + - Interpretation of ESC codes (tau) + + The escape codes and their meaning are described in the + technical reference of this program. +*/ + +// Tokens ------------------------------------------------------------------ -- + +/* + Since the tokens are the central notion if this section, we've put them + in front. They provide the syntactical elements used to represent the + terminals operations as byte sequences. + + They are encodes here into a single machine word, so that we can later + switch over them easily. Depending on the token itself, additional + argument variables are filled with parameter values. + + The tokens are defined below: + + - CHR - Printable characters (32..255 but DEL (=127)) + - CTL - Control characters (0..31 but ESC (= 27), DEL) + - ESC - Escape codes of the form + - ESC_DE - Escape codes of the form C + - CSI_PN - Escape codes of the form '[' {Pn} ';' {Pn} C + - CSI_PS - Escape codes of the form '[' {Pn} ';' ... C + - CSI_PR - Escape codes of the form '[' '?' {Pn} ';' ... C + - VT52 - VT52 escape codes + - + - 'Y'{Pc}{Pc} + - XTE_HA - Xterm hacks `]' {Pn} `;' {Text} + note that this is handled differently + + The last two forms allow list of arguments. Since the elements of + the lists are treated individually the same way, they are passed + as individual tokens to the interpretation. Further, because the + meaning of the parameters are names (althought represented as numbers), + they are includes within the token ('N'). + +*/ + +#define TY_CONSTR(T,A,N) ( ((((int)N) & 0xffff) << 16) | ((((int)A) & 0xff) << 8) | (((int)T) & 0xff) ) + +#define TY_CHR___( ) TY_CONSTR(0,0,0) +#define TY_CTL___(A ) TY_CONSTR(1,A,0) +#define TY_ESC___(A ) TY_CONSTR(2,A,0) +#define TY_ESC_CS(A,B) TY_CONSTR(3,A,B) +#define TY_ESC_DE(A ) TY_CONSTR(4,A,0) +#define TY_CSI_PS(A,N) TY_CONSTR(5,A,N) +#define TY_CSI_PN(A ) TY_CONSTR(6,A,0) +#define TY_CSI_PR(A,N) TY_CONSTR(7,A,N) + +#define TY_VT52__(A ) TY_CONSTR(8,A,0) + +// Tokenizer --------------------------------------------------------------- -- + +/* The tokenizers state + + The state is represented by the buffer (pbuf, ppos), + and accompanied by decoded arguments kept in (argv,argc). + Note that they are kept internal in the tokenizer. +*/ + +void TEmuVt102::resetToken() +{ + ppos = 0; argc = 0; argv[0] = 0; argv[1] = 0; +} + +void TEmuVt102::addDigit(int dig) +{ + argv[argc] = 10*argv[argc] + dig; +} + +void TEmuVt102::addArgument() +{ + argc = QMIN(argc+1,MAXARGS-1); + argv[argc] = 0; +} + +void TEmuVt102::pushToToken(int cc) +{ + pbuf[ppos] = cc; + ppos = QMIN(ppos+1,MAXPBUF-1); +} + +// Character Classes used while decoding + +#define CTL 1 +#define CHR 2 +#define CPN 4 +#define DIG 8 +#define SCS 16 +#define GRP 32 + +void TEmuVt102::initTokenizer() +{ int i; UINT8* s; + for(i = 0; i < 256; i++) tbl[ i] = 0; + for(i = 0; i < 32; i++) tbl[ i] |= CTL; + for(i = 32; i < 256; i++) tbl[ i] |= CHR; + for(s = (UINT8*)"@ABCDGHLMPXcdfry"; *s; s++) tbl[*s] |= CPN; + for(s = (UINT8*)"0123456789" ; *s; s++) tbl[*s] |= DIG; + for(s = (UINT8*)"()+*%" ; *s; s++) tbl[*s] |= SCS; + for(s = (UINT8*)"()+*#[]%" ; *s; s++) tbl[*s] |= GRP; + resetToken(); +} + +/* Ok, here comes the nasty part of the decoder. + + Instead of keeping an explicit state, we deduce it from the + token scanned so far. It is then immediately combined with + the current character to form a scanning decision. + + This is done by the following defines. + + - P is the length of the token scanned so far. + - L (often P-1) is the position on which contents we base a decision. + - C is a character or a group of characters (taken from 'tbl'). + + Note that they need to applied in proper order. +*/ + +#define lec(P,L,C) (p == (P) && s[(L)] == (C)) +#define lun( ) (p == 1 && cc >= 32 ) +#define les(P,L,C) (p == (P) && s[L] < 256 && (tbl[s[(L)]] & (C)) == (C)) +#define eec(C) (p >= 3 && cc == (C)) +#define ees(C) (p >= 3 && cc < 256 && (tbl[ cc ] & (C)) == (C)) +#define eps(C) (p >= 3 && s[2] != '?' && cc < 256 && (tbl[ cc ] & (C)) == (C)) +#define epp( ) (p >= 3 && s[2] == '?' ) +#define egt( ) (p == 3 && s[2] == '>' ) +#define Xpe (ppos>=2 && pbuf[1] == ']' ) +#define Xte (Xpe && cc == 7 ) +#define ces(C) ( cc < 256 && (tbl[ cc ] & (C)) == (C) && !Xte) + +#define ESC 27 +#define CNTL(c) ((c)-'@') + +// process an incoming unicode character + +void TEmuVt102::onRcvChar(int cc) +{ int i; + + if (cc == 127) return; //VT100: ignore. + + if (ces( CTL)) + { // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100 + // This means, they do neither a resetToken nor a pushToToken. Some of them, do + // of course. Guess this originates from a weakly layered handling of the X-on + // X-off protocol, which comes really below this level. + if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC) resetToken(); //VT100: CAN or SUB + if (cc != ESC) { tau( TY_CTL___(cc+'@' ), 0, 0); return; } + } + + pushToToken(cc); // advance the state + + int* s = pbuf; + int p = ppos; + + if (getMode(MODE_Ansi)) // decide on proper action + { + if (lec(1,0,ESC)) { return; } + if (les(2,1,GRP)) { return; } + if (Xte ) { XtermHack(); resetToken(); return; } + if (Xpe ) { return; } + if (lec(3,2,'?')) { return; } + if (lec(3,2,'>')) { return; } + if (lun( )) { tau( TY_CHR___(), applyCharset(cc), 0); resetToken(); return; } + if (lec(2,0,ESC)) { tau( TY_ESC___(s[1]), 0, 0); resetToken(); return; } + if (les(3,1,SCS)) { tau( TY_ESC_CS(s[1],s[2]), 0, 0); resetToken(); return; } + if (lec(3,1,'#')) { tau( TY_ESC_DE(s[2]), 0, 0); resetToken(); return; } +// if (egt( )) { tau( TY_CSI_PG(cc ), '>', 0); resetToken(); return; } + if (eps( CPN)) { tau( TY_CSI_PN(cc), argv[0],argv[1]); resetToken(); return; } + if (ees( DIG)) { addDigit(cc-'0'); return; } + if (eec( ';')) { addArgument(); return; } + for (i=0;i<=argc;i++) + if (epp( )) tau( TY_CSI_PR(cc,argv[i]), 0, 0); else + tau( TY_CSI_PS(cc,argv[i]), 0, 0); + resetToken(); + } + else // mode VT52 + { + if (lec(1,0,ESC)) return; + if (les(1,0,CHR)) { tau( TY_CHR___( ), s[0], 0); resetToken(); return; } + if (lec(2,1,'Y')) return; + if (lec(3,1,'Y')) return; + if (p < 4) { tau( TY_VT52__(s[1] ), 0, 0); resetToken(); return; } + tau( TY_VT52__(s[1] ), s[2],s[3]); resetToken(); return; + } +} + +void TEmuVt102::XtermHack() +{ int i,arg = 0; + for (i = 2; i < ppos && '0'<=pbuf[i] && pbuf[i]<'9' ; i++) + arg = 10*arg + (pbuf[i]-'0'); + if (pbuf[i] != ';') { ReportErrorToken(); return; } + QChar *str = new QChar[ppos-i-2]; + for (int j = 0; j < ppos-i-2; j++) str[j] = pbuf[i+1+j]; + QString unistr(str,ppos-i-2); + // arg == 1 doesn't change the title. In XTerm it only changes the icon name + // (btw: arg=0 changes title and icon, arg=1 only icon, arg=2 only title + if (arg == 0 || arg == 2) emit changeTitle(arg,unistr); + delete [] str; +} + +// Interpreting Codes --------------------------------------------------------- + +/* + Now that the incoming character stream is properly tokenized, + meaning is assigned to them. These are either operations of + the current screen, or of the emulation class itself. + + The token to be interpreteted comes in as a machine word + possibly accompanied by two parameters. + + Likewise, the operations assigned to, come with up to two + arguments. One could consider to make up a proper table + from the function below. + + The technical reference manual provides more informations + about this mapping. +*/ + +void TEmuVt102::tau( int token, int p, int q ) +{ +//scan_buffer_report(); +//if (token == TY_CHR___()) printf("%c",p); else +//printf("tau(%d,%d,%d, %d,%d)\n",(token>>0)&0xff,(token>>8)&0xff,(token>>16)&0xffff,p,q); + switch (token) + { + + case TY_CHR___( ) : scr->ShowCharacter (p ); break; //UTF16 + + // 127 DEL : ignored on input + + case TY_CTL___('@' ) : /* NUL: ignored */ break; + case TY_CTL___('A' ) : /* SOH: ignored */ break; + case TY_CTL___('B' ) : /* STX: ignored */ break; + case TY_CTL___('C' ) : /* ETX: ignored */ break; + case TY_CTL___('D' ) : /* EOT: ignored */ break; + case TY_CTL___('E' ) : reportAnswerBack ( ); break; //VT100 + case TY_CTL___('F' ) : /* ACK: ignored */ break; + case TY_CTL___('G' ) : gui->Bell ( ); break; //VT100 + case TY_CTL___('H' ) : scr->BackSpace ( ); break; //VT100 + case TY_CTL___('I' ) : scr->Tabulate ( ); break; //VT100 + case TY_CTL___('J' ) : scr->NewLine ( ); break; //VT100 + case TY_CTL___('K' ) : scr->NewLine ( ); break; //VT100 + case TY_CTL___('L' ) : scr->NewLine ( ); break; //VT100 + case TY_CTL___('M' ) : scr->Return ( ); break; //VT100 + + case TY_CTL___('N' ) : useCharset ( 1); break; //VT100 + case TY_CTL___('O' ) : useCharset ( 0); break; //VT100 + + case TY_CTL___('P' ) : /* DLE: ignored */ break; + case TY_CTL___('Q' ) : /* DC1: XON continue */ break; //VT100 + case TY_CTL___('R' ) : /* DC2: ignored */ break; + case TY_CTL___('S' ) : /* DC3: XOFF halt */ break; //VT100 + case TY_CTL___('T' ) : /* DC4: ignored */ break; + case TY_CTL___('U' ) : /* NAK: ignored */ break; + case TY_CTL___('V' ) : /* SYN: ignored */ break; + case TY_CTL___('W' ) : /* ETB: ignored */ break; + case TY_CTL___('X' ) : scr->ShowCharacter ( 0x2592); break; //VT100 + case TY_CTL___('Y' ) : /* EM : ignored */ break; + case TY_CTL___('Z' ) : scr->ShowCharacter ( 0x2592); break; //VT100 + case TY_CTL___('[' ) : /* ESC: cannot be seen here. */ break; + case TY_CTL___('\\' ) : /* FS : ignored */ break; + case TY_CTL___(']' ) : /* GS : ignored */ break; + case TY_CTL___('^' ) : /* RS : ignored */ break; + case TY_CTL___('_' ) : /* US : ignored */ break; + + case TY_ESC___('D' ) : scr->index ( ); break; //VT100 + case TY_ESC___('E' ) : scr->NextLine ( ); break; //VT100 + case TY_ESC___('H' ) : scr->changeTabStop (TRUE ); break; //VT100 + case TY_ESC___('M' ) : scr->reverseIndex ( ); break; //VT100 + case TY_ESC___('Z' ) : reportTerminalType ( ); break; + case TY_ESC___('c' ) : reset ( ); break; + + case TY_ESC___('n' ) : useCharset ( 2); break; + case TY_ESC___('o' ) : useCharset ( 3); break; + case TY_ESC___('7' ) : saveCursor ( ); break; + case TY_ESC___('8' ) : restoreCursor ( ); break; + + case TY_ESC___('=' ) : setMode (MODE_AppKeyPad); break; + case TY_ESC___('>' ) : resetMode (MODE_AppKeyPad); break; + case TY_ESC___('<' ) : setMode (MODE_Ansi ); break; //VT100 + + case TY_ESC_CS('(', '0') : setCharset (0, '0'); break; //VT100 + case TY_ESC_CS('(', 'A') : setCharset (0, 'A'); break; //VT100 + case TY_ESC_CS('(', 'B') : setCharset (0, 'B'); break; //VT100 + + case TY_ESC_CS(')', '0') : setCharset (1, '0'); break; //VT100 + case TY_ESC_CS(')', 'A') : setCharset (1, 'A'); break; //VT100 + case TY_ESC_CS(')', 'B') : setCharset (1, 'B'); break; //VT100 + + case TY_ESC_CS('*', '0') : setCharset (2, '0'); break; //VT100 + case TY_ESC_CS('*', 'A') : setCharset (2, 'A'); break; //VT100 + case TY_ESC_CS('*', 'B') : setCharset (2, 'B'); break; //VT100 + + case TY_ESC_CS('+', '0') : setCharset (3, '0'); break; //VT100 + case TY_ESC_CS('+', 'A') : setCharset (3, 'A'); break; //VT100 + case TY_ESC_CS('+', 'B') : setCharset (3, 'B'); break; //VT100 + + case TY_ESC_CS('%', 'G') : setCodec (1 ); break; //LINUX + case TY_ESC_CS('%', '@') : setCodec (0 ); break; //LINUX + + case TY_ESC_DE('3' ) : /* IGNORED: double high, top half */ break; + case TY_ESC_DE('4' ) : /* IGNORED: double high, bottom half */ break; + case TY_ESC_DE('5' ) : /* IGNORED: single width, single high*/ break; + case TY_ESC_DE('6' ) : /* IGNORED: double width, single high*/ break; + case TY_ESC_DE('8' ) : scr->helpAlign ( ); break; + + case TY_CSI_PS('K', 0) : scr->clearToEndOfLine ( ); break; + case TY_CSI_PS('K', 1) : scr->clearToBeginOfLine ( ); break; + case TY_CSI_PS('K', 2) : scr->clearEntireLine ( ); break; + case TY_CSI_PS('J', 0) : scr->clearToEndOfScreen ( ); break; + case TY_CSI_PS('J', 1) : scr->clearToBeginOfScreen ( ); break; + case TY_CSI_PS('J', 2) : scr->clearEntireScreen ( ); break; + case TY_CSI_PS('g', 0) : scr->changeTabStop (FALSE ); break; //VT100 + case TY_CSI_PS('g', 3) : scr->clearTabStops ( ); break; //VT100 + case TY_CSI_PS('h', 4) : scr-> setMode (MODE_Insert ); break; + case TY_CSI_PS('h', 20) : setMode (MODE_NewLine ); break; + case TY_CSI_PS('i', 0) : /* IGNORE: attached printer */ break; //VT100 + case TY_CSI_PS('l', 4) : scr-> resetMode (MODE_Insert ); break; + case TY_CSI_PS('l', 20) : resetMode (MODE_NewLine ); break; + + case TY_CSI_PS('m', 0) : scr->setDefaultRendition ( ); break; + case TY_CSI_PS('m', 1) : scr-> setRendition (RE_BOLD ); break; //VT100 + case TY_CSI_PS('m', 4) : scr-> setRendition (RE_UNDERLINE); break; //VT100 + case TY_CSI_PS('m', 5) : scr-> setRendition (RE_BLINK ); break; //VT100 + case TY_CSI_PS('m', 7) : scr-> setRendition (RE_REVERSE ); break; + case TY_CSI_PS('m', 10) : /* IGNORED: mapping related */ break; //LINUX + case TY_CSI_PS('m', 11) : /* IGNORED: mapping related */ break; //LINUX + case TY_CSI_PS('m', 12) : /* IGNORED: mapping related */ break; //LINUX + case TY_CSI_PS('m', 22) : scr->resetRendition (RE_BOLD ); break; + case TY_CSI_PS('m', 24) : scr->resetRendition (RE_UNDERLINE); break; + case TY_CSI_PS('m', 25) : scr->resetRendition (RE_BLINK ); break; + case TY_CSI_PS('m', 27) : scr->resetRendition (RE_REVERSE ); break; + + case TY_CSI_PS('m', 30) : scr->setForeColor ( 0); break; + case TY_CSI_PS('m', 31) : scr->setForeColor ( 1); break; + case TY_CSI_PS('m', 32) : scr->setForeColor ( 2); break; + case TY_CSI_PS('m', 33) : scr->setForeColor ( 3); break; + case TY_CSI_PS('m', 34) : scr->setForeColor ( 4); break; + case TY_CSI_PS('m', 35) : scr->setForeColor ( 5); break; + case TY_CSI_PS('m', 36) : scr->setForeColor ( 6); break; + case TY_CSI_PS('m', 37) : scr->setForeColor ( 7); break; + case TY_CSI_PS('m', 39) : scr->setForeColorToDefault( ); break; + + case TY_CSI_PS('m', 40) : scr->setBackColor ( 0); break; + case TY_CSI_PS('m', 41) : scr->setBackColor ( 1); break; + case TY_CSI_PS('m', 42) : scr->setBackColor ( 2); break; + case TY_CSI_PS('m', 43) : scr->setBackColor ( 3); break; + case TY_CSI_PS('m', 44) : scr->setBackColor ( 4); break; + case TY_CSI_PS('m', 45) : scr->setBackColor ( 5); break; + case TY_CSI_PS('m', 46) : scr->setBackColor ( 6); break; + case TY_CSI_PS('m', 47) : scr->setBackColor ( 7); break; + case TY_CSI_PS('m', 49) : scr->setBackColorToDefault( ); break; + + case TY_CSI_PS('m', 90) : scr->setForeColor ( 8); break; + case TY_CSI_PS('m', 91) : scr->setForeColor ( 9); break; + case TY_CSI_PS('m', 92) : scr->setForeColor ( 10); break; + case TY_CSI_PS('m', 93) : scr->setForeColor ( 11); break; + case TY_CSI_PS('m', 94) : scr->setForeColor ( 12); break; + case TY_CSI_PS('m', 95) : scr->setForeColor ( 13); break; + case TY_CSI_PS('m', 96) : scr->setForeColor ( 14); break; + case TY_CSI_PS('m', 97) : scr->setForeColor ( 15); break; + + case TY_CSI_PS('m', 100) : scr->setBackColor ( 8); break; + case TY_CSI_PS('m', 101) : scr->setBackColor ( 9); break; + case TY_CSI_PS('m', 102) : scr->setBackColor ( 10); break; + case TY_CSI_PS('m', 103) : scr->setBackColor ( 11); break; + case TY_CSI_PS('m', 104) : scr->setBackColor ( 12); break; + case TY_CSI_PS('m', 105) : scr->setBackColor ( 13); break; + case TY_CSI_PS('m', 106) : scr->setBackColor ( 14); break; + case TY_CSI_PS('m', 107) : scr->setBackColor ( 15); break; + + case TY_CSI_PS('n', 5) : reportStatus ( ); break; + case TY_CSI_PS('n', 6) : reportCursorPosition ( ); break; + case TY_CSI_PS('q', 0) : /* IGNORED: LEDs off */ break; //VT100 + case TY_CSI_PS('q', 1) : /* IGNORED: LED1 on */ break; //VT100 + case TY_CSI_PS('q', 2) : /* IGNORED: LED2 on */ break; //VT100 + case TY_CSI_PS('q', 3) : /* IGNORED: LED3 on */ break; //VT100 + case TY_CSI_PS('q', 4) : /* IGNORED: LED4 on */ break; //VT100 + case TY_CSI_PS('x', 0) : reportTerminalParms ( 2); break; //VT100 + case TY_CSI_PS('x', 1) : reportTerminalParms ( 3); break; //VT100 + + case TY_CSI_PN('@' ) : scr->insertChars (p ); break; + case TY_CSI_PN('A' ) : scr->cursorUp (p ); break; //VT100 + case TY_CSI_PN('B' ) : scr->cursorDown (p ); break; //VT100 + case TY_CSI_PN('C' ) : scr->cursorRight (p ); break; //VT100 + case TY_CSI_PN('D' ) : scr->cursorLeft (p ); break; //VT100 + case TY_CSI_PN('G' ) : scr->setCursorX (p ); break; //LINUX + case TY_CSI_PN('H' ) : scr->setCursorYX (p, q); break; //VT100 + case TY_CSI_PN('L' ) : scr->insertLines (p ); break; + case TY_CSI_PN('M' ) : scr->deleteLines (p ); break; + case TY_CSI_PN('P' ) : scr->deleteChars (p ); break; + case TY_CSI_PN('X' ) : scr->eraseChars (p ); break; + case TY_CSI_PN('c' ) : reportTerminalType ( ); break; //VT100 + case TY_CSI_PN('d' ) : scr->setCursorY (p ); break; //LINUX + case TY_CSI_PN('f' ) : scr->setCursorYX (p, q); break; //VT100 + case TY_CSI_PN('r' ) : scr->setMargins (p, q); break; //VT100 + case TY_CSI_PN('y' ) : /* IGNORED: Confidence test */ break; //VT100 + + case TY_CSI_PR('h', 1) : setMode (MODE_AppCuKeys); break; //VT100 + case TY_CSI_PR('l', 1) : resetMode (MODE_AppCuKeys); break; //VT100 + case TY_CSI_PR('s', 1) : saveMode (MODE_AppCuKeys); break; //FIXME + case TY_CSI_PR('r', 1) : restoreMode (MODE_AppCuKeys); break; //FIXME + + case TY_CSI_PR('l', 2) : resetMode (MODE_Ansi ); break; //VT100 + + case TY_CSI_PR('h', 3) : setColumns ( 132); break; //VT100 + case TY_CSI_PR('l', 3) : setColumns ( 80); break; //VT100 + + case TY_CSI_PR('h', 4) : /* IGNORED: soft scrolling */ break; //VT100 + case TY_CSI_PR('l', 4) : /* IGNORED: soft scrolling */ break; //VT100 + + case TY_CSI_PR('h', 5) : scr-> setMode (MODE_Screen ); break; //VT100 + case TY_CSI_PR('l', 5) : scr-> resetMode (MODE_Screen ); break; //VT100 + + case TY_CSI_PR('h', 6) : scr-> setMode (MODE_Origin ); break; //VT100 + case TY_CSI_PR('l', 6) : scr-> resetMode (MODE_Origin ); break; //VT100 + case TY_CSI_PR('s', 6) : scr-> saveMode (MODE_Origin ); break; //FIXME + case TY_CSI_PR('r', 6) : scr->restoreMode (MODE_Origin ); break; //FIXME + + case TY_CSI_PR('h', 7) : scr-> setMode (MODE_Wrap ); break; //VT100 + case TY_CSI_PR('l', 7) : scr-> resetMode (MODE_Wrap ); break; //VT100 + case TY_CSI_PR('s', 7) : scr-> saveMode (MODE_Wrap ); break; //FIXME + case TY_CSI_PR('r', 7) : scr->restoreMode (MODE_Wrap ); break; //FIXME + + case TY_CSI_PR('h', 8) : /* IGNORED: autorepeat on */ break; //VT100 + case TY_CSI_PR('l', 8) : /* IGNORED: autorepeat off */ break; //VT100 + + case TY_CSI_PR('h', 9) : /* IGNORED: interlace */ break; //VT100 + case TY_CSI_PR('l', 9) : /* IGNORED: interlace */ break; //VT100 + + case TY_CSI_PR('h', 25) : setMode (MODE_Cursor ); break; //VT100 + case TY_CSI_PR('l', 25) : resetMode (MODE_Cursor ); break; //VT100 + + case TY_CSI_PR('h', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM + case TY_CSI_PR('l', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM + case TY_CSI_PR('s', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM + case TY_CSI_PR('r', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM + + case TY_CSI_PR('h', 47) : setMode (MODE_AppScreen); break; //VT100 + case TY_CSI_PR('l', 47) : resetMode (MODE_AppScreen); break; //VT100 + + case TY_CSI_PR('h', 1000) : setMode (MODE_Mouse1000); break; //XTERM + case TY_CSI_PR('l', 1000) : resetMode (MODE_Mouse1000); break; //XTERM + case TY_CSI_PR('s', 1000) : saveMode (MODE_Mouse1000); break; //XTERM + case TY_CSI_PR('r', 1000) : restoreMode (MODE_Mouse1000); break; //XTERM + + case TY_CSI_PR('h', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM + case TY_CSI_PR('l', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM + case TY_CSI_PR('s', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM + case TY_CSI_PR('r', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM + + case TY_CSI_PR('h', 1047) : setMode (MODE_AppScreen); break; //XTERM + case TY_CSI_PR('l', 1047) : resetMode (MODE_AppScreen); break; //XTERM + + //FIXME: Unitoken: save translations + case TY_CSI_PR('h', 1048) : saveCursor ( ); break; //XTERM + case TY_CSI_PR('l', 1048) : restoreCursor ( ); break; //XTERM + + //FIXME: every once new sequences like this pop up in xterm. + // Here's a guess of what they could mean. + case TY_CSI_PR('h', 1049) : setMode (MODE_AppScreen); break; //XTERM + case TY_CSI_PR('l', 1049) : resetMode (MODE_AppScreen); break; //XTERM + + //FIXME: when changing between vt52 and ansi mode evtl do some resetting. + case TY_VT52__('A' ) : scr->cursorUp ( 1); break; //VT52 + case TY_VT52__('B' ) : scr->cursorDown ( 1); break; //VT52 + case TY_VT52__('C' ) : scr->cursorRight ( 1); break; //VT52 + case TY_VT52__('D' ) : scr->cursorLeft ( 1); break; //VT52 + + case TY_VT52__('F' ) : setAndUseCharset (0, '0'); break; //VT52 + case TY_VT52__('G' ) : setAndUseCharset (0, 'B'); break; //VT52 + + case TY_VT52__('H' ) : scr->setCursorYX (1,1 ); break; //VT52 + case TY_VT52__('I' ) : scr->reverseIndex ( ); break; //VT52 + case TY_VT52__('J' ) : scr->clearToEndOfScreen ( ); break; //VT52 + case TY_VT52__('K' ) : scr->clearToEndOfLine ( ); break; //VT52 + case TY_VT52__('Y' ) : scr->setCursorYX (p-31,q-31 ); break; //VT52 + case TY_VT52__('Z' ) : reportTerminalType ( ); break; //VT52 + case TY_VT52__('<' ) : setMode (MODE_Ansi ); break; //VT52 + case TY_VT52__('=' ) : setMode (MODE_AppKeyPad); break; //VT52 + case TY_VT52__('>' ) : resetMode (MODE_AppKeyPad); break; //VT52 + + default : ReportErrorToken(); break; + }; +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Terminal to Host protocol */ +/* */ +/* ------------------------------------------------------------------------- */ + +/* + Outgoing bytes originate from several sources: + + - Replies to Enquieries. + - Mouse Events + - Keyboard Events +*/ + +/*! +*/ + +void TEmuVt102::sendString(const char* s) +{ + emit sndBlock(s,strlen(s)); +} + +// Replies ----------------------------------------------------------------- -- + +// This section copes with replies send as response to an enquiery control code. + +/*! +*/ + +void TEmuVt102::reportCursorPosition() +{ char tmp[20]; + sprintf(tmp,"\033[%d;%dR",scr->getCursorY()+1,scr->getCursorX()+1); + sendString(tmp); +} + +/* + What follows here is rather obsolete and faked stuff. + The correspondent enquieries are neverthenless issued. +*/ + +/*! +*/ + +void TEmuVt102::reportTerminalType() +{ +//FIXME: should change? + if (getMode(MODE_Ansi)) +// sendString("\033[?1;2c"); // I'm a VT100 with AP0 //FIXME: send only in response to ^[[0c + sendString("\033[>0;115;0c"); // I'm a VT220 //FIXME: send only in response to ^[[>c + else + sendString("\033/Z"); // I'm a VT52 +} + +void TEmuVt102::reportTerminalParms(int p) +// DECREPTPARM +{ char tmp[100]; + sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true. + sendString(tmp); +} + +/*! +*/ + +void TEmuVt102::reportStatus() +{ + sendString("\033[0n"); //VT100. Device status report. 0 = Ready. +} + +/*! +*/ + +#define ANSWER_BACK "" // This is really obsolete VT100 stuff. + +void TEmuVt102::reportAnswerBack() +{ + sendString(ANSWER_BACK); +} + +// Mouse Handling ---------------------------------------------------------- -- + +/*! + Mouse clicks are possibly reported to the client + application if it has issued interest in them. + They are normally consumed by the widget for copy + and paste, but may be propagated from the widget + when gui->setMouseMarks is set via setMode(MODE_Mouse1000). + + `x',`y' are 1-based. + `ev' (event) indicates the button pressed (0-2) + or a general mouse release (3). +*/ + +void TEmuVt102::onMouse( int cb, int cx, int cy ) +{ char tmp[20]; + if (!connected) return; + sprintf(tmp,"\033[M%c%c%c",cb+040,cx+040,cy+040); + sendString(tmp); +} + +// Keyboard Handling ------------------------------------------------------- -- + +#define encodeMode(M,B) BITS(B,getMode(M)) +#define encodeStat(M,B) BITS(B,((ev->state() & (M)) == (M))) + +/* + Keyboard event handling has been simplified somewhat by pushing + the complications towards a configuration file [see KeyTrans class]. +*/ + +void TEmuVt102::onKeyPress( QKeyEvent* ev ) +{ + if (!connected) return; // someone else gets the keys + +//printf("State/Key: 0x%04x 0x%04x (%d,%d)\n",ev->state(),ev->key(),ev->text().length(),ev->text().length()?ev->text().ascii()[0]:0); + + // revert to non-history when typing + if (scr->getHistCursor() != scr->getHistLines()); + scr->setHistCursor(scr->getHistLines()); + + // lookup in keyboard translation table ... + int cmd; const char* txt; int len; + if (keytrans->findEntry(ev->key(), encodeMode(MODE_NewLine , BITS_NewLine ) + // OLD, + encodeMode(MODE_Ansi , BITS_Ansi ) + // OBSOLETE, + encodeMode(MODE_AppCuKeys, BITS_AppCuKeys ) + // VT100 stuff + encodeStat(ControlButton , BITS_Control ) + + encodeStat(ShiftButton , BITS_Shift ) + + encodeStat(AltButton , BITS_Alt ), + &cmd, &txt, &len )) +//printf("cmd: %d, %s, %d\n",cmd,txt,len); + switch(cmd) // ... and execute if found. + { + case CMD_emitSelection : gui->emitSelection(); return; + case CMD_scrollPageUp : gui->doScroll(-gui->Lines()/2); return; + case CMD_scrollPageDown : gui->doScroll(+gui->Lines()/2); return; + case CMD_scrollLineUp : gui->doScroll(-1 ); return; + case CMD_scrollLineDown : gui->doScroll(+1 ); return; + case CMD_send : emit sndBlock(txt,len); return; + case CMD_prevSession : emit prevSession(); return; + case CMD_nextSession : emit nextSession(); return; + } + + // fall back handling + if (!ev->text().isEmpty()) + { + if (ev->state() & AltButton) sendString("\033"); // ESC, this is the ALT prefix + QCString s = codec->fromUnicode(ev->text()); // encode for application + emit sndBlock(s.data(),s.length()); // we may well have s.length() > 1 + return; + } +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* VT100 Charsets */ +/* */ +/* ------------------------------------------------------------------------- */ + +// Character Set Conversion ------------------------------------------------ -- + +/* + The processing contains a VT100 specific code translation layer. + It's still in use and mainly responsible for the line drawing graphics. + + These and some other glyphs are assigned to codes (0x5f-0xfe) + normally occupied by the latin letters. Since this codes also + appear within control sequences, the extra code conversion + does not permute with the tokenizer and is placed behind it + in the pipeline. It only applies to tokens, which represent + plain characters. + + This conversion it eventually continued in TEWidget.C, since + it might involve VT100 enhanced fonts, which have these + particular glyphs allocated in (0x00-0x1f) in their code page. +*/ + +#define CHARSET charset[scr==screen[1]] + +// Apply current character map. + +unsigned short TEmuVt102::applyCharset(unsigned short c) +{ + if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f]; + if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete + return c; +} + +/* + "Charset" related part of the emulation state. + This configures the VT100 charset filter. + + While most operation work on the current screen, + the following two are different. +*/ + +void TEmuVt102::resetCharset(int scrno) +{ + charset[scrno].cu_cs = 0; + strncpy(charset[scrno].charset,"BBBB",4); + charset[scrno].sa_graphic = FALSE; + charset[scrno].sa_pound = FALSE; + charset[scrno].graphic = FALSE; + charset[scrno].pound = FALSE; +} + +/*! +*/ + +void TEmuVt102::setCharset(int n, int cs) // on both screens. +{ + charset[0].charset[n&3] = cs; useCharset(charset[0].cu_cs); + charset[1].charset[n&3] = cs; useCharset(charset[1].cu_cs); +} + +/*! +*/ + +void TEmuVt102::setAndUseCharset(int n, int cs) +{ + CHARSET.charset[n&3] = cs; + useCharset(n&3); +} + +/*! +*/ + +void TEmuVt102::useCharset(int n) +{ + CHARSET.cu_cs = n&3; + CHARSET.graphic = (CHARSET.charset[n&3] == '0'); + CHARSET.pound = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete +} + +/*! Save the cursor position and the rendition attribute settings. */ + +void TEmuVt102::saveCursor() +{ + CHARSET.sa_graphic = CHARSET.graphic; + CHARSET.sa_pound = CHARSET.pound; //This mode is obsolete + // we are not clear about these + //sa_charset = charsets[cScreen->charset]; + //sa_charset_num = cScreen->charset; + scr->saveCursor(); +} + +/*! Restore the cursor position and the rendition attribute settings. */ + +void TEmuVt102::restoreCursor() +{ + CHARSET.graphic = CHARSET.sa_graphic; + CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete + scr->restoreCursor(); +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Mode Operations */ +/* */ +/* ------------------------------------------------------------------------- */ + +/* + Some of the emulations state is either added to the state of the screens. + + This causes some scoping problems, since different emulations choose to + located the mode either to the current screen or to both. + + For strange reasons, the extend of the rendition attributes ranges over + all screens and not over the actual screen. + + We decided on the precise precise extend, somehow. +*/ + +// "Mode" related part of the state. These are all booleans. + +void TEmuVt102::resetModes() +{ + resetMode(MODE_Mouse1000); saveMode(MODE_Mouse1000); + resetMode(MODE_AppScreen); saveMode(MODE_AppScreen); + // here come obsolete modes + resetMode(MODE_AppCuKeys); saveMode(MODE_AppCuKeys); + resetMode(MODE_NewLine ); + setMode(MODE_Ansi ); +} + +void TEmuVt102::setMode(int m) +{ + currParm.mode[m] = TRUE; + switch (m) + { + case MODE_Mouse1000 : gui->setMouseMarks(FALSE); + break; + case MODE_AppScreen : screen[1]->clearSelection(); + screen[1]->clearEntireScreen(); + setScreen(1); + break; + } + if (m < MODES_SCREEN || m == MODE_NewLine) + { + screen[0]->setMode(m); + screen[1]->setMode(m); + } +} + +void TEmuVt102::resetMode(int m) +{ + currParm.mode[m] = FALSE; + switch (m) + { + case MODE_Mouse1000 : gui->setMouseMarks(TRUE); + break; + case MODE_AppScreen : screen[0]->clearSelection(); + setScreen(0); + break; + } + if (m < MODES_SCREEN || m == MODE_NewLine) + { + screen[0]->resetMode(m); + screen[1]->resetMode(m); + } +} + +void TEmuVt102::saveMode(int m) +{ + saveParm.mode[m] = currParm.mode[m]; +} + +void TEmuVt102::restoreMode(int m) +{ + if(saveParm.mode[m]) setMode(m); else resetMode(m); +} + +BOOL TEmuVt102::getMode(int m) +{ + return currParm.mode[m]; +} + +void TEmuVt102::setConnect(bool c) +{ + TEmulation::setConnect(c); + if (c) + { // refresh mouse mode + if (getMode(MODE_Mouse1000)) + setMode(MODE_Mouse1000); + else + resetMode(MODE_Mouse1000); + } +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Diagnostic */ +/* */ +/* ------------------------------------------------------------------------- */ + +/*! shows the contents of the scan buffer. + + This functions is used for diagnostics. It is called by \e ReportErrorToken + to inform about strings that cannot be decoded or handled by the emulation. + + \sa ReportErrorToken +*/ + +/*! +*/ + +static void hexdump(int* s, int len) +{ int i; + for (i = 0; i < len; i++) + { + if (s[i] == '\\') + printf("\\\\"); + else + if ((s[i]) > 32 && s[i] < 127) + printf("%c",s[i]); + else + printf("\\%04x(hex)",s[i]); + } +} + +void TEmuVt102::scan_buffer_report() +{ + if (ppos == 0 || ppos == 1 && (pbuf[0] & 0xff) >= 32) return; + printf("token: "); hexdump(pbuf,ppos); printf("\n"); +} + +/*! +*/ + +void TEmuVt102::ReportErrorToken() +{ + printf("undecodable "); scan_buffer_report(); +} diff --git a/core/apps/embeddedkonsole/TEmuVt102.h b/core/apps/embeddedkonsole/TEmuVt102.h new file mode 100644 index 0000000..a448a71 --- a/dev/null +++ b/core/apps/embeddedkonsole/TEmuVt102.h @@ -0,0 +1,135 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [TEmuVt102.h] X Terminal Emulation */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +#ifndef VT102EMU_H +#define VT102EMU_H + +#include "TEWidget.h" +#include "TEScreen.h" +#include "TEmulation.h" +#include +#include + +// + +#define MODE_AppScreen (MODES_SCREEN+0) +#define MODE_AppCuKeys (MODES_SCREEN+1) +#define MODE_AppKeyPad (MODES_SCREEN+2) +#define MODE_Mouse1000 (MODES_SCREEN+3) +#define MODE_Ansi (MODES_SCREEN+4) +#define MODE_total (MODES_SCREEN+5) + +struct DECpar +{ + BOOL mode[MODE_total]; +}; + +struct CharCodes +{ + // coding info + char charset[4]; // + int cu_cs; // actual charset. + bool graphic; // Some VT100 tricks + bool pound ; // Some VT100 tricks + bool sa_graphic; // saved graphic + bool sa_pound; // saved pound +}; + +class TEmuVt102 : public TEmulation +{ Q_OBJECT + +public: + + TEmuVt102(TEWidget* gui); + ~TEmuVt102(); + +public slots: // signals incoming from TEWidget + + void onKeyPress(QKeyEvent*); + void onMouse(int cb, int cx, int cy); + +signals: + + void changeTitle(int,const QString&); + void prevSession(); + void nextSession(); + +public: + + void reset(); + + void onRcvChar(int cc); + void sendString(const char *); + +public: + + BOOL getMode (int m); + + void setMode (int m); + void resetMode (int m); + void saveMode (int m); + void restoreMode(int m); + void resetModes(); + + void setConnect(bool r); + +private: + + void resetToken(); +#define MAXPBUF 80 + void pushToToken(int cc); + int pbuf[MAXPBUF]; //FIXME: overflow? + int ppos; +#define MAXARGS 15 + void addDigit(int dig); + void addArgument(); + int argv[MAXARGS]; + int argc; + void initTokenizer(); + int tbl[256]; + + void scan_buffer_report(); //FIXME: rename + void ReportErrorToken(); //FIXME: rename + + void tau(int code, int p, int q); + void XtermHack(); + + // + + void reportTerminalType(); + void reportStatus(); + void reportAnswerBack(); + void reportCursorPosition(); + void reportTerminalParms(int p); + +protected: + + unsigned short applyCharset(unsigned short c); + void setCharset(int n, int cs); + void useCharset(int n); + void setAndUseCharset(int n, int cs); + void saveCursor(); + void restoreCursor(); + void resetCharset(int scrno); + CharCodes charset[2]; + + DECpar currParm; + DECpar saveParm; +}; + +#endif // ifndef ANSIEMU_H diff --git a/core/apps/embeddedkonsole/TEmulation.cpp b/core/apps/embeddedkonsole/TEmulation.cpp new file mode 100644 index 0000000..6f3ad32 --- a/dev/null +++ b/core/apps/embeddedkonsole/TEmulation.cpp @@ -0,0 +1,363 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [TEmulation.cpp] Terminal Emulation Decoder */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +/*! \class TEmulation + + \brief Mediator between TEWidget and TEScreen. + + This class is responsible to scan the escapes sequences of the terminal + emulation and to map it to their corresponding semantic complements. + Thus this module knows mainly about decoding escapes sequences and + is a stateless device w.r.t. the semantics. + + It is also responsible to refresh the TEWidget by certain rules. + + \sa TEWidget \sa TEScreen + + \par A note on refreshing + + Although the modifications to the current screen image could immediately + be propagated via `TEWidget' to the graphical surface, we have chosen + another way here. + + The reason for doing so is twofold. + + First, experiments show that directly displaying the operation results + in slowing down the overall performance of emulations. Displaying + individual characters using X11 creates a lot of overhead. + + Second, by using the following refreshing method, the screen operations + can be completely separated from the displaying. This greatly simplifies + the programmer's task of coding and maintaining the screen operations, + since one need not worry about differential modifications on the + display affecting the operation of concern. + + We use a refreshing algorithm here that has been adoped from rxvt/kvt. + + By this, refreshing is driven by a timer, which is (re)started whenever + a new bunch of data to be interpreted by the emulation arives at `onRcvBlock'. + As soon as no more data arrive for `BULK_TIMEOUT' milliseconds, we trigger + refresh. This rule suits both bulk display operation as done by curses as + well as individual characters typed. + (BULK_TIMEOUT < 1000 / max characters received from keyboard per second). + + Additionally, we trigger refreshing by newlines comming in to make visual + snapshots of lists as produced by `cat', `ls' and likely programs, thereby + producing the illusion of a permanent and immediate display operation. + + As a sort of catch-all needed for cases where none of the above + conditions catch, the screen refresh is also triggered by a count + of incoming bulks (`bulk_incnt'). +*/ + +/* FIXME + - evtl. the bulk operations could be made more transparent. +*/ + +#include "TEmulation.h" +#include "TEWidget.h" +#include "TEScreen.h" +#include +#include +#include +#include + + +/* ------------------------------------------------------------------------- */ +/* */ +/* TEmulation */ +/* */ +/* ------------------------------------------------------------------------- */ + +#define CNTL(c) ((c)-'@') + +/*! +*/ + +TEmulation::TEmulation(TEWidget* gui) +: decoder((QTextDecoder*)NULL) +{ + this->gui = gui; + + screen[0] = new TEScreen(gui->Lines(),gui->Columns()); + screen[1] = new TEScreen(gui->Lines(),gui->Columns()); + scr = screen[0]; + + bulk_nlcnt = 0; // reset bulk newline counter + bulk_incnt = 0; // reset bulk counter + connected = FALSE; + + QObject::connect(&bulk_timer, SIGNAL(timeout()), this, SLOT(showBulk()) ); + QObject::connect(gui,SIGNAL(changedImageSizeSignal(int,int)), + this,SLOT(onImageSizeChange(int,int))); + QObject::connect(gui,SIGNAL(changedHistoryCursor(int)), + this,SLOT(onHistoryCursorChange(int))); + QObject::connect(gui,SIGNAL(keyPressedSignal(QKeyEvent*)), + this,SLOT(onKeyPress(QKeyEvent*))); + QObject::connect(gui,SIGNAL(beginSelectionSignal(const int,const int)), + this,SLOT(onSelectionBegin(const int,const int)) ); + QObject::connect(gui,SIGNAL(extendSelectionSignal(const int,const int)), + this,SLOT(onSelectionExtend(const int,const int)) ); + QObject::connect(gui,SIGNAL(endSelectionSignal(const BOOL)), + this,SLOT(setSelection(const BOOL)) ); + QObject::connect(gui,SIGNAL(clearSelectionSignal()), + this,SLOT(clearSelection()) ); +} + +/*! +*/ + +TEmulation::~TEmulation() +{ + delete screen[0]; + delete screen[1]; + bulk_timer.stop(); +} + +/*! change between primary and alternate screen +*/ + +void TEmulation::setScreen(int n) +{ + scr = screen[n&1]; +} + +void TEmulation::setHistory(bool on) +{ + screen[0]->setScroll(on); + if (!connected) return; + showBulk(); +} + +bool TEmulation::history() +{ + return screen[0]->hasScroll(); +} + +void TEmulation::setCodec(int c) +{ + //FIXME: check whether we have to free codec + codec = c ? QTextCodec::codecForName("utf8") + : QTextCodec::codecForLocale(); + if (decoder) delete decoder; + decoder = codec->makeDecoder(); +} + +void TEmulation::setKeytrans(int no) +{ + keytrans = KeyTrans::find(no); +} + +void TEmulation::setKeytrans(const char * no) +{ + keytrans = KeyTrans::find(no); +} + +// Interpreting Codes --------------------------------------------------------- + +/* + This section deals with decoding the incoming character stream. + Decoding means here, that the stream is first seperated into `tokens' + which are then mapped to a `meaning' provided as operations by the + `Screen' class. +*/ + +/*! +*/ + +void TEmulation::onRcvChar(int c) +// process application unicode input to terminal +// this is a trivial scanner +{ + c &= 0xff; + switch (c) + { + case '\b' : scr->BackSpace(); break; + case '\t' : scr->Tabulate(); break; + case '\n' : scr->NewLine(); break; + case '\r' : scr->Return(); break; + case 0x07 : gui->Bell(); break; + default : scr->ShowCharacter(c); break; + }; +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Keyboard Handling */ +/* */ +/* ------------------------------------------------------------------------- */ + +/*! +*/ + +void TEmulation::onKeyPress( QKeyEvent* ev ) +{ + if (!connected) return; // someone else gets the keys + if (scr->getHistCursor() != scr->getHistLines()); + scr->setHistCursor(scr->getHistLines()); + if (!ev->text().isEmpty()) + { // A block of text + // Note that the text is proper unicode. + // We should do a conversion here, but since this + // routine will never be used, we simply emit plain ascii. + emit sndBlock(ev->text().ascii(),ev->text().length()); + } + else if (ev->ascii()>0) + { unsigned char c[1]; + c[0] = ev->ascii(); + emit sndBlock((char*)c,1); + } +} + +// Unblocking, Byte to Unicode translation --------------------------------- -- + +/* + We are doing code conversion from locale to unicode first. +*/ + +void TEmulation::onRcvBlock(const char *s, int len) +{ + bulkStart(); + bulk_incnt += 1; + for (int i = 0; i < len; i++) + { + QString result = decoder->toUnicode(&s[i],1); + int reslen = result.length(); + for (int j = 0; j < reslen; j++) + onRcvChar(result[j].unicode()); + if (s[i] == '\n') bulkNewline(); + } + bulkEnd(); +} + +// Selection --------------------------------------------------------------- -- + +void TEmulation::onSelectionBegin(const int x, const int y) { + if (!connected) return; + scr->setSelBeginXY(x,y); + showBulk(); +} + +void TEmulation::onSelectionExtend(const int x, const int y) { + if (!connected) return; + scr->setSelExtentXY(x,y); + showBulk(); +} + +void TEmulation::setSelection(const BOOL preserve_line_breaks) { + if (!connected) return; + QString t = scr->getSelText(preserve_line_breaks); + if (!t.isNull()) gui->setSelection(t); +} + +void TEmulation::clearSelection() { + if (!connected) return; + scr->clearSelection(); + showBulk(); +} + +// Refreshing -------------------------------------------------------------- -- + +#define BULK_TIMEOUT 20 + +/*! + called when \n comes in. Evtl. triggers showBulk at endBulk +*/ + +void TEmulation::bulkNewline() +{ + bulk_nlcnt += 1; + bulk_incnt = 0; // reset bulk counter since `nl' rule applies +} + +/*! +*/ + +void TEmulation::showBulk() +{ + bulk_nlcnt = 0; // reset bulk newline counter + bulk_incnt = 0; // reset bulk counter + if (connected) + { + ca* image = scr->getCookedImage(); // get the image + gui->setImage(image, + scr->getLines(), + scr->getColumns()); // actual refresh + free(image); + //FIXME: check that we do not trigger other draw event here. + gui->setScroll(scr->getHistCursor(),scr->getHistLines()); + } +} + +void TEmulation::bulkStart() +{ + if (bulk_timer.isActive()) bulk_timer.stop(); +} + +void TEmulation::bulkEnd() +{ + if ( bulk_nlcnt > gui->Lines() || bulk_incnt > 20 ) + showBulk(); // resets bulk_??cnt to 0, too. + else + bulk_timer.start(BULK_TIMEOUT,TRUE); +} + +void TEmulation::setConnect(bool c) +{ + connected = c; + if ( connected) + { + onImageSizeChange(gui->Lines(), gui->Columns()); + showBulk(); + } + else + { + scr->clearSelection(); + } +} + +// --------------------------------------------------------------------------- + +/*! triggered by image size change of the TEWidget `gui'. + + This event is simply propagated to the attached screens + and to the related serial line. +*/ + +void TEmulation::onImageSizeChange(int lines, int columns) +{ + if (!connected) return; + screen[0]->resizeImage(lines,columns); + screen[1]->resizeImage(lines,columns); + showBulk(); + emit ImageSizeChanged(lines,columns); // propagate event to serial line +} + +void TEmulation::onHistoryCursorChange(int cursor) +{ + if (!connected) return; + scr->setHistCursor(cursor); + showBulk(); +} + +void TEmulation::setColumns(int columns) +{ + //FIXME: this goes strange ways. + // Can we put this straight or explain it at least? + emit changeColumns(columns); +} diff --git a/core/apps/embeddedkonsole/TEmulation.h b/core/apps/embeddedkonsole/TEmulation.h new file mode 100644 index 0000000..ec15e7a --- a/dev/null +++ b/core/apps/embeddedkonsole/TEmulation.h @@ -0,0 +1,117 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [emulation.h] Fundamental Terminal Emulation */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +#ifndef EMULATION_H +#define EMULATION_H + +#include "TEWidget.h" +#include "TEScreen.h" +#include +#include +#include +#include "keytrans.h" + +class TEmulation : public QObject +{ Q_OBJECT + +public: + + TEmulation(TEWidget* gui); + ~TEmulation(); + +public: + virtual void setHistory(bool on); + virtual bool history(); + +public slots: // signals incoming from TEWidget + + virtual void onImageSizeChange(int lines, int columns); + virtual void onHistoryCursorChange(int cursor); + virtual void onKeyPress(QKeyEvent*); + + virtual void clearSelection(); + virtual void onSelectionBegin(const int x, const int y); + virtual void onSelectionExtend(const int x, const int y); + virtual void setSelection(const BOOL preserve_line_breaks); + +public slots: // signals incoming from data source + + void onRcvBlock(const char* txt,int len); + +signals: + + void sndBlock(const char* txt,int len); + void ImageSizeChanged(int lines, int columns); + void changeColumns(int columns); + void changeTitle(int arg, const char* str); + +public: + + virtual void onRcvChar(int); + + virtual void setMode (int) = 0; + virtual void resetMode(int) = 0; + + virtual void sendString(const char*) = 0; + + virtual void setConnect(bool r); + void setColumns(int columns); + + void setKeytrans(int no); + void setKeytrans(const char * no); + +protected: + + TEWidget* gui; + TEScreen* scr; // referes to one `screen' + TEScreen* screen[2]; // 0 = primary, 1 = alternate + void setScreen(int n); // set `scr' to `screen[n]' + + bool connected; // communicate with widget + + void setCodec(int c); // codec number, 0 = locale, 1=utf8 + + QTextCodec* codec; + QTextCodec* localeCodec; + QTextDecoder* decoder; + + KeyTrans* keytrans; + +// refreshing related material. +// this is localized in the class. +private slots: // triggered by timer + + void showBulk(); + +private: + + void bulkNewline(); + void bulkStart(); + void bulkEnd(); + +private: + + QTimer bulk_timer; + int bulk_nlcnt; // bulk newline counter + char* SelectedText; + int bulk_incnt; // bulk counter + + +}; + +#endif // ifndef EMULATION_H diff --git a/core/apps/embeddedkonsole/default.keytab.h b/core/apps/embeddedkonsole/default.keytab.h new file mode 100644 index 0000000..503ea46 --- a/dev/null +++ b/core/apps/embeddedkonsole/default.keytab.h @@ -0,0 +1,103 @@ + /* generated by '../tests/quote ../other/default.Keytab' */ + + "# [default.Keytab] Buildin Keyboard Table\n" + "\n" + "# --------------------------------------------------------------\n" + "#\n" + "# This file in included only for reference purposes. \n" + "#\n" + "# Modifying it does not have any effect (unless you\n" + "# derive the default.keytab.h and recompile konsole).\n" + "#\n" + "# To customize your keyboard, copy this file to something\n" + "# ending with .keytab and change it to meet you needs.\n" + "#\n" + "# --------------------------------------------------------------\n" + "\n" + "keyboard \"xterm (default)\"\n" + "\n" + "# --------------------------------------------------------------\n" + "#\n" + "# The syntax of each entry has the form\n" + "#\n" + "# \"key\" Keyname { (\"+\"|\"-\") Modename } \":\" (String|Operation)\n" + "#\n" + "# Keynames are those defined in \n" + "# with the \"Qt::Key_\" prefix removed.\n" + "#\n" + "# Mode names are: Shift, Alt, Control.\n" + "#\n" + "# If the key is not found here, the text of the\n" + "# key event as provided by QT is emitted, possibly\n" + "# preceeded by ESC if the Alt key is pressed.\n" + "#\n" + "# --------------------------------------------------------------\n" + "#\n" + "# Note that this particular table is a \"risc\" version made to\n" + "# ease customization without bothering with obsolete details.\n" + "# See VT100.keytab for the more hairy stuff.\n" + "#\n" + "# --------------------------------------------------------------\n" + "\n" + "# common keys\n" + "\n" + "key Escape : \"\\E\"\n" + "key Tab : \"\\t\"\n" + "\n" + "key Return-Alt : \"\\r\"\n" + "key Return+Alt : \"\\E\\r\"\n" + "\n" + "# Backspace and Delete codes are preserving CTRL-H.\n" + "\n" + "key Backspace : \"\\x7f\"\n" + "\n" + "# cursor keys\n" + "\n" + "key Up -Shift : \"\\EOA\"\n" + "key Down -Shift : \"\\EOB\"\n" + "key Right -Shift : \"\\EOC\"\n" + "key Left -Shift : \"\\EOD\"\n" + "\n" + "# other grey PC keys\n" + "\n" + "key Enter : \"\\r\"\n" + "\n" + "key Home : \"\\E[1~\"\n" + "key Insert-Shift : \"\\E[2~\"\n" + "key Delete : \"\\E[3~\"\n" + "key End : \"\\E[4~\"\n" + "key Prior -Shift : \"\\E[5~\"\n" + "key Next -Shift : \"\\E[6~\"\n" + "\n" + "# function keys\n" + "\n" + "key F1 : \"\\E[11~\"\n" + "key F2 : \"\\E[12~\"\n" + "key F3 : \"\\E[13~\"\n" + "key F4 : \"\\E[14~\"\n" + "key F5 : \"\\E[15~\"\n" + "key F6 : \"\\E[17~\"\n" + "key F7 : \"\\E[18~\"\n" + "key F8 : \"\\E[19~\"\n" + "key F9 : \"\\E[20~\"\n" + "key F10 : \"\\E[21~\"\n" + "key F11 : \"\\E[23~\"\n" + "key F12 : \"\\E[24~\"\n" + "\n" + "# Work around dead keys\n" + "\n" + "key Space +Control : \"\\x00\"\n" + "\n" + "# Some keys are used by konsole to cause operations.\n" + "# The scroll* operations refer to the history buffer.\n" + "\n" + "key Left +Shift : prevSession\n" + "key Right +Shift : nextSession\n" + "key Up +Shift : scrollLineUp\n" + "key Prior +Shift : scrollPageUp\n" + "key Down +Shift : scrollLineDown\n" + "key Next +Shift : scrollPageDown\n" + "key Insert+Shift : emitSelection\n" + "\n" + "# keypad characters are not offered differently by Qt.\n" + "" diff --git a/core/apps/embeddedkonsole/embeddedkonsole.pro b/core/apps/embeddedkonsole/embeddedkonsole.pro new file mode 100755 index 0000000..b757ea5 --- a/dev/null +++ b/core/apps/embeddedkonsole/embeddedkonsole.pro @@ -0,0 +1,38 @@ +TEMPLATE = app + +CONFIG += qt warn_on release + +DESTDIR = $(QPEDIR)/bin + +HEADERS = TEWidget.h \ + TEScreen.h \ + TECommon.h \ + TEHistory.h \ + TEmulation.h \ + TEmuVt102.h \ + session.h \ + keytrans.h \ + konsole.h \ + MyPty.h + +SOURCES = TEScreen.cpp \ + TEWidget.cpp \ + TEHistory.cpp \ + TEmulation.cpp \ + TEmuVt102.cpp \ + session.cpp \ + keytrans.cpp \ + konsole.cpp \ + main.cpp \ + MyPty.cpp + +TARGET = embeddedkonsole + +INCLUDEPATH += $(QPEDIR)/include + +DEPENDPATH += $(QPEDIR)/include + +LIBS += -lqpe + +REQUIRES = embeddedkonsole + diff --git a/core/apps/embeddedkonsole/faded_bg.png b/core/apps/embeddedkonsole/faded_bg.png new file mode 100644 index 0000000..7dbf6b4 --- a/dev/null +++ b/core/apps/embeddedkonsole/faded_bg.png Binary files differ diff --git a/core/apps/embeddedkonsole/keytrans.cpp b/core/apps/embeddedkonsole/keytrans.cpp new file mode 100644 index 0000000..d569ae0 --- a/dev/null +++ b/core/apps/embeddedkonsole/keytrans.cpp @@ -0,0 +1,706 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [keytrans.C] Keyboard Translation */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +/* + The keyboard translation table allows to configure konsoles behavior + on key strokes. + + FIXME: some bug crept in, disallowing '\0' to be emitted. +*/ + +#include "keytrans.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +//#include +//nclude + +#include + + +#undef USE_APPDATA_DIR + + +#define HERE printf("%s(%d): here\n",__FILE__,__LINE__) + +/* KeyEntry + + instances represent the individual assignments +*/ + +KeyTrans::KeyEntry::KeyEntry(int _ref, int _key, int _bits, int _mask, int _cmd, QString _txt) +: ref(_ref), key(_key), bits(_bits), mask(_mask), cmd(_cmd), txt(_txt) +{ +} + +KeyTrans::KeyEntry::~KeyEntry() +{ +} + +bool KeyTrans::KeyEntry::matches(int _key, int _bits, int _mask) +{ int m = mask & _mask; + return _key == key && (bits & m) == (_bits & m); +} + +QString KeyTrans::KeyEntry::text() +{ + return txt; +} + +/* KeyTrans + + combines the individual assignments to a proper map + Takes part in a collection themself. +*/ + +KeyTrans::KeyTrans() +{ + path = ""; + numb = 0; +} + +KeyTrans::~KeyTrans() +{ +} + +KeyTrans::KeyEntry* KeyTrans::addEntry(int ref, int key, int bits, int mask, int cmd, QString txt) +// returns conflicting entry +{ + for (QListIterator it(table); it.current(); ++it) + { + if (it.current()->matches(key,bits,mask)) + { + return it.current(); + } + } + table.append(new KeyEntry(ref,key,bits,mask,cmd,txt)); + return (KeyEntry*)NULL; +} + +bool KeyTrans::findEntry(int key, int bits, int* cmd, const char** txt, int* len) +{ + for (QListIterator it(table); it.current(); ++it) + if (it.current()->matches(key,bits,0xffff)) + { + *cmd = it.current()->cmd; + *txt = it.current()->txt.ascii(); + *len = it.current()->txt.length(); + return TRUE; + } + return FALSE; +} + +/* ------------------------------------------------------------------------- */ +/* */ +/* Scanner for keyboard configuration */ +/* */ +/* ------------------------------------------------------------------------- */ + +// regular tokenizer +/* Tokens + - Spaces + - Name (A-Za-z0-9)+ + - String + - Opr on of +-: +*/ + +#define SYMName 0 +#define SYMString 1 +#define SYMEol 2 +#define SYMEof 3 +#define SYMOpr 4 +#define SYMError 5 + +#define inRange(L,X,H) ((L <= X) && (X <= H)) +#define isNibble(X) (inRange('A',X,'F')||inRange('a',X,'f')||inRange('0',X,'9')) +#define convNibble(X) (inRange('0',X,'9')?X-'0':X+10-(inRange('A',X,'F')?'A':'a')) + +class KeytabReader +{ +public: + KeytabReader(QString p, QIODevice &d); +public: + void getCc(); + void getSymbol(); + void parseTo(KeyTrans* kt); + void ReportError(const char* msg); + void ReportToken(); // diagnostic +private: + int sym; + QString res; + int len; + int slinno; + int scolno; +private: + int cc; + int linno; + int colno; + QIODevice* buf; + QString path; +}; + + +KeytabReader::KeytabReader(QString p, QIODevice &d) +{ + path = p; + buf = &d; + cc = 0; +} + +void KeytabReader::getCc() +{ + if (cc == '\n') { linno += 1; colno = 0; } + if (cc < 0) return; + cc = buf->getch(); + colno += 1; +} + +void KeytabReader::getSymbol() +{ + res = ""; len = 0; sym = SYMError; + while (cc == ' ') getCc(); // skip spaces + if (cc == '#') // skip comment + { + while (cc != '\n' && cc > 0) getCc(); + } + slinno = linno; + scolno = colno; + if (cc <= 0) + { + sym = SYMEof; return; // eos + } + if (cc == '\n') + { + getCc(); + sym = SYMEol; return; // eol + } + if (inRange('A',cc,'Z')||inRange('a',cc,'z')||inRange('0',cc,'9')) + { + while (inRange('A',cc,'Z') || inRange('a',cc,'z') || inRange('0',cc,'9')) + { + res = res + (char)cc; + getCc(); + } + sym = SYMName; + return; + } + if (strchr("+-:",cc)) + { + res = ""; + res = res + (char)cc; + getCc(); + sym = SYMOpr; return; + } + if (cc == '"') + { + getCc(); + while (cc >= ' ' && cc != '"') + { int sc; + if (cc == '\\') // handle quotation + { + getCc(); + switch (cc) + { + case 'E' : sc = 27; getCc(); break; + case 'b' : sc = 8; getCc(); break; + case 'f' : sc = 12; getCc(); break; + case 't' : sc = 9; getCc(); break; + case 'r' : sc = 13; getCc(); break; + case 'n' : sc = 10; getCc(); break; + case '\\' : // fall thru + case '"' : sc = cc; getCc(); break; + case 'x' : getCc(); + sc = 0; + if (!isNibble(cc)) return; sc = 16*sc + convNibble(cc); getCc(); + if (!isNibble(cc)) return; sc = 16*sc + convNibble(cc); getCc(); + break; + default : return; + } + } + else + { + // regular char + sc = cc; getCc(); + } + res = res + (char)sc; + len = len + 1; + } + if (cc != '"') return; + getCc(); + sym = SYMString; return; + } +} + +void KeytabReader::ReportToken() // diagnostic +{ + printf("sym(%d): ",slinno); + switch(sym) + { + case SYMEol : printf("End of line"); break; + case SYMEof : printf("End of file"); break; + case SYMName : printf("Name: %s",res.latin1()); break; + case SYMOpr : printf("Opr : %s",res.latin1()); break; + case SYMString : printf("String len %d,%d ",res.length(),len); + for (unsigned i = 0; i < res.length(); i++) + printf(" %02x(%c)",res.latin1()[i],res.latin1()[i]>=' '?res.latin1()[i]:'?'); + break; + } + printf("\n"); +} + +void KeytabReader::ReportError(const char* msg) // diagnostic +{ + fprintf(stderr,"%s(%d,%d):error: %s.\n",path.ascii(),slinno,scolno,msg); +} + +// local symbol tables --------------------------------------------------------------------- + +class KeyTransSymbols +{ +public: + KeyTransSymbols(); +protected: + void defOprSyms(); + void defModSyms(); + void defKeySyms(); + void defKeySym(const char* key, int val); + void defOprSym(const char* key, int val); + void defModSym(const char* key, int val); +public: + QDict keysyms; + QDict modsyms; + QDict oprsyms; +}; + +static KeyTransSymbols * syms = 0L; + +// parser ---------------------------------------------------------------------------------- +/* Syntax + - Line :: [KeyName { ("+" | "-") ModeName } ":" (String|CommandName)] "\n" + - Comment :: '#' (any but \n)* +*/ + +KeyTrans* KeyTrans::fromDevice(QString path, QIODevice &buf) +{ + KeyTrans* kt = new KeyTrans; + kt->path = path; + KeytabReader ktr(path,buf); ktr.parseTo(kt); + return kt; +} + + +#define assertSyntax(Cond,Message) if (!(Cond)) { ReportError(Message); goto ERROR; } + +void KeytabReader::parseTo(KeyTrans* kt) +{ + // Opening sequence + + buf->open(IO_ReadOnly); + getCc(); + linno = 1; + colno = 1; + getSymbol(); + +Loop: + // syntax: ["key" KeyName { ("+" | "-") ModeName } ":" String/CommandName] ["#" Comment] + if (sym == SYMName && !strcmp(res.latin1(),"keyboard")) + { + getSymbol(); assertSyntax(sym == SYMString, "Header expected") + kt->hdr = res.latin1(); + getSymbol(); assertSyntax(sym == SYMEol, "Text unexpected") + getSymbol(); // eoln + goto Loop; + } + if (sym == SYMName && !strcmp(res.latin1(),"key")) + { +//printf("line %3d: ",startofsym); + getSymbol(); assertSyntax(sym == SYMName, "Name expected") + assertSyntax(syms->keysyms[res], "Unknown key name") + int key = (int)syms->keysyms[res]-1; +//printf(" key %s (%04x)",res.latin1(),(int)syms->keysyms[res]-1); + getSymbol(); // + - : + int mode = 0; + int mask = 0; + while (sym == SYMOpr && (!strcmp(res.latin1(),"+") || !strcmp(res.latin1(),"-"))) + { + bool on = !strcmp(res.latin1(),"+"); + getSymbol(); + // mode name + assertSyntax(sym == SYMName, "Name expected") + assertSyntax(syms->modsyms[res], "Unknown mode name") + int bits = (int)syms->modsyms[res]-1; + if (mask & (1 << bits)) + { + fprintf(stderr,"%s(%d,%d): mode name used multible times.\n",path.ascii(),slinno,scolno); + } + else + { + mode |= (on << bits); + mask |= (1 << bits); + } +//printf(", mode %s(%d) %s",res.latin1(),(int)syms->modsyms[res]-1,on?"on":"off"); + getSymbol(); + } + assertSyntax(sym == SYMOpr && !strcmp(res.latin1(),":"), "':' expected") + getSymbol(); + // string or command + assertSyntax(sym == SYMName || sym == SYMString,"Command or string expected") + int cmd = 0; + if (sym == SYMName) + { + assertSyntax(syms->oprsyms[res], "Unknown operator name") + cmd = (int)syms->oprsyms[res]-1; +//printf(": do %s(%d)",res.latin1(),(int)syms->oprsyms[res]-1); + } + if (sym == SYMString) + { + cmd = CMD_send; +//printf(": send"); +//for (unsigned i = 0; i < res.length(); i++) +//printf(" %02x(%c)",res.latin1()[i],res.latin1()[i]>=' '?res.latin1()[i]:'?'); + } +//printf(". summary %04x,%02x,%02x,%d\n",key,mode,mask,cmd); + KeyTrans::KeyEntry* ke = kt->addEntry(slinno,key,mode,mask,cmd,res); + if (ke) + { + fprintf(stderr,"%s(%d): keystroke already assigned in line %d.\n",path.ascii(),slinno,ke->ref); + } + getSymbol(); + assertSyntax(sym == SYMEol, "Unexpected text") + goto Loop; + } + if (sym == SYMEol) + { + getSymbol(); + goto Loop; + } + + assertSyntax(sym == SYMEof, "Undecodable Line") + + buf->close(); + return; + +ERROR: + while (sym != SYMEol && sym != SYMEof) getSymbol(); // eoln + goto Loop; +} + + +KeyTrans* KeyTrans::defaultKeyTrans() +{ + QCString txt = +#include "default.keytab.h" + ; + QBuffer buf(txt); + return fromDevice("[buildin]",buf); +} + +KeyTrans* KeyTrans::fromFile(const char* path) +{ + QFile file(path); + return fromDevice(path,file); +} + +// local symbol tables --------------------------------------------------------------------- +// material needed for parsing the config file. +// This is incomplete work. + +void KeyTransSymbols::defKeySym(const char* key, int val) +{ + keysyms.insert(key,(QObject*)(val+1)); +} + +void KeyTransSymbols::defOprSym(const char* key, int val) +{ + oprsyms.insert(key,(QObject*)(val+1)); +} + +void KeyTransSymbols::defModSym(const char* key, int val) +{ + modsyms.insert(key,(QObject*)(val+1)); +} + +void KeyTransSymbols::defOprSyms() +{ + // Modifier + defOprSym("scrollLineUp", CMD_scrollLineUp ); + defOprSym("scrollLineDown",CMD_scrollLineDown); + defOprSym("scrollPageUp", CMD_scrollPageUp ); + defOprSym("scrollPageDown",CMD_scrollPageDown); + defOprSym("emitSelection", CMD_emitSelection ); + defOprSym("prevSession", CMD_prevSession ); + defOprSym("nextSession", CMD_nextSession ); +} + +void KeyTransSymbols::defModSyms() +{ + // Modifier + defModSym("Shift", BITS_Shift ); + defModSym("Control", BITS_Control ); + defModSym("Alt", BITS_Alt ); + // Modes + defModSym("BsHack", BITS_BsHack ); // deprecated + defModSym("Ansi", BITS_Ansi ); + defModSym("NewLine", BITS_NewLine ); + defModSym("AppCuKeys", BITS_AppCuKeys ); +} + +void KeyTransSymbols::defKeySyms() +{ + // Grey keys + defKeySym("Escape", Qt::Key_Escape ); + defKeySym("Tab", Qt::Key_Tab ); + defKeySym("Backtab", Qt::Key_Backtab ); + defKeySym("Backspace", Qt::Key_Backspace ); + defKeySym("Return", Qt::Key_Return ); + defKeySym("Enter", Qt::Key_Enter ); + defKeySym("Insert", Qt::Key_Insert ); + defKeySym("Delete", Qt::Key_Delete ); + defKeySym("Pause", Qt::Key_Pause ); + defKeySym("Print", Qt::Key_Print ); + defKeySym("SysReq", Qt::Key_SysReq ); + defKeySym("Home", Qt::Key_Home ); + defKeySym("End", Qt::Key_End ); + defKeySym("Left", Qt::Key_Left ); + defKeySym("Up", Qt::Key_Up ); + defKeySym("Right", Qt::Key_Right ); + defKeySym("Down", Qt::Key_Down ); + defKeySym("Prior", Qt::Key_Prior ); + defKeySym("Next", Qt::Key_Next ); + defKeySym("Shift", Qt::Key_Shift ); + defKeySym("Control", Qt::Key_Control ); + defKeySym("Meta", Qt::Key_Meta ); + defKeySym("Alt", Qt::Key_Alt ); + defKeySym("CapsLock", Qt::Key_CapsLock ); + defKeySym("NumLock", Qt::Key_NumLock ); + defKeySym("ScrollLock", Qt::Key_ScrollLock ); + defKeySym("F1", Qt::Key_F1 ); + defKeySym("F2", Qt::Key_F2 ); + defKeySym("F3", Qt::Key_F3 ); + defKeySym("F4", Qt::Key_F4 ); + defKeySym("F5", Qt::Key_F5 ); + defKeySym("F6", Qt::Key_F6 ); + defKeySym("F7", Qt::Key_F7 ); + defKeySym("F8", Qt::Key_F8 ); + defKeySym("F9", Qt::Key_F9 ); + defKeySym("F10", Qt::Key_F10 ); + defKeySym("F11", Qt::Key_F11 ); + defKeySym("F12", Qt::Key_F12 ); + defKeySym("F13", Qt::Key_F13 ); + defKeySym("F14", Qt::Key_F14 ); + defKeySym("F15", Qt::Key_F15 ); + defKeySym("F16", Qt::Key_F16 ); + defKeySym("F17", Qt::Key_F17 ); + defKeySym("F18", Qt::Key_F18 ); + defKeySym("F19", Qt::Key_F19 ); + defKeySym("F20", Qt::Key_F20 ); + defKeySym("F21", Qt::Key_F21 ); + defKeySym("F22", Qt::Key_F22 ); + defKeySym("F23", Qt::Key_F23 ); + defKeySym("F24", Qt::Key_F24 ); + defKeySym("F25", Qt::Key_F25 ); + defKeySym("F26", Qt::Key_F26 ); + defKeySym("F27", Qt::Key_F27 ); + defKeySym("F28", Qt::Key_F28 ); + defKeySym("F29", Qt::Key_F29 ); + defKeySym("F30", Qt::Key_F30 ); + defKeySym("F31", Qt::Key_F31 ); + defKeySym("F32", Qt::Key_F32 ); + defKeySym("F33", Qt::Key_F33 ); + defKeySym("F34", Qt::Key_F34 ); + defKeySym("F35", Qt::Key_F35 ); + defKeySym("Super_L", Qt::Key_Super_L ); + defKeySym("Super_R", Qt::Key_Super_R ); + defKeySym("Menu", Qt::Key_Menu ); + defKeySym("Hyper_L", Qt::Key_Hyper_L ); + defKeySym("Hyper_R", Qt::Key_Hyper_R ); + + // Regular keys + defKeySym("Space", Qt::Key_Space ); + defKeySym("Exclam", Qt::Key_Exclam ); + defKeySym("QuoteDbl", Qt::Key_QuoteDbl ); + defKeySym("NumberSign", Qt::Key_NumberSign ); + defKeySym("Dollar", Qt::Key_Dollar ); + defKeySym("Percent", Qt::Key_Percent ); + defKeySym("Ampersand", Qt::Key_Ampersand ); + defKeySym("Apostrophe", Qt::Key_Apostrophe ); + defKeySym("ParenLeft", Qt::Key_ParenLeft ); + defKeySym("ParenRight", Qt::Key_ParenRight ); + defKeySym("Asterisk", Qt::Key_Asterisk ); + defKeySym("Plus", Qt::Key_Plus ); + defKeySym("Comma", Qt::Key_Comma ); + defKeySym("Minus", Qt::Key_Minus ); + defKeySym("Period", Qt::Key_Period ); + defKeySym("Slash", Qt::Key_Slash ); + defKeySym("0", Qt::Key_0 ); + defKeySym("1", Qt::Key_1 ); + defKeySym("2", Qt::Key_2 ); + defKeySym("3", Qt::Key_3 ); + defKeySym("4", Qt::Key_4 ); + defKeySym("5", Qt::Key_5 ); + defKeySym("6", Qt::Key_6 ); + defKeySym("7", Qt::Key_7 ); + defKeySym("8", Qt::Key_8 ); + defKeySym("9", Qt::Key_9 ); + defKeySym("Colon", Qt::Key_Colon ); + defKeySym("Semicolon", Qt::Key_Semicolon ); + defKeySym("Less", Qt::Key_Less ); + defKeySym("Equal", Qt::Key_Equal ); + defKeySym("Greater", Qt::Key_Greater ); + defKeySym("Question", Qt::Key_Question ); + defKeySym("At", Qt::Key_At ); + defKeySym("A", Qt::Key_A ); + defKeySym("B", Qt::Key_B ); + defKeySym("C", Qt::Key_C ); + defKeySym("D", Qt::Key_D ); + defKeySym("E", Qt::Key_E ); + defKeySym("F", Qt::Key_F ); + defKeySym("G", Qt::Key_G ); + defKeySym("H", Qt::Key_H ); + defKeySym("I", Qt::Key_I ); + defKeySym("J", Qt::Key_J ); + defKeySym("K", Qt::Key_K ); + defKeySym("L", Qt::Key_L ); + defKeySym("M", Qt::Key_M ); + defKeySym("N", Qt::Key_N ); + defKeySym("O", Qt::Key_O ); + defKeySym("P", Qt::Key_P ); + defKeySym("Q", Qt::Key_Q ); + defKeySym("R", Qt::Key_R ); + defKeySym("S", Qt::Key_S ); + defKeySym("T", Qt::Key_T ); + defKeySym("U", Qt::Key_U ); + defKeySym("V", Qt::Key_V ); + defKeySym("W", Qt::Key_W ); + defKeySym("X", Qt::Key_X ); + defKeySym("Y", Qt::Key_Y ); + defKeySym("Z", Qt::Key_Z ); + defKeySym("BracketLeft", Qt::Key_BracketLeft ); + defKeySym("Backslash", Qt::Key_Backslash ); + defKeySym("BracketRight", Qt::Key_BracketRight); + defKeySym("AsciiCircum", Qt::Key_AsciiCircum ); + defKeySym("Underscore", Qt::Key_Underscore ); + defKeySym("QuoteLeft", Qt::Key_QuoteLeft ); + defKeySym("BraceLeft", Qt::Key_BraceLeft ); + defKeySym("Bar", Qt::Key_Bar ); + defKeySym("BraceRight", Qt::Key_BraceRight ); + defKeySym("AsciiTilde", Qt::Key_AsciiTilde ); +} + +KeyTransSymbols::KeyTransSymbols() +{ + defModSyms(); + defOprSyms(); + defKeySyms(); +} + +// Global material ----------------------------------------------------------- + +static int keytab_serial = 0; //FIXME: remove,localize + +static QIntDict * numb2keymap = 0L; +static QDict * path2keymap = 0L; + +KeyTrans* KeyTrans::find(int numb) +{ + KeyTrans* res = numb2keymap->find(numb); + return res ? res : numb2keymap->find(0); +} + +KeyTrans* KeyTrans::find(const char* path) +{ + KeyTrans* res = path2keymap->find(path); + return res ? res : numb2keymap->find(0); +} + +int KeyTrans::count() +{ + return numb2keymap->count(); +} + +void KeyTrans::addKeyTrans() +{ + this->numb = keytab_serial ++; + numb2keymap->insert(numb,this); + path2keymap->insert(path,this); +} + +void KeyTrans::loadAll() +{ + if (!numb2keymap) + numb2keymap = new QIntDict; + if (!path2keymap) + path2keymap = new QDict; + if (!syms) + syms = new KeyTransSymbols; + + defaultKeyTrans()->addKeyTrans(); + + + QString path = QPEApplication::qpeDir() + "etc/keytabs"; + QDir dir(path); + QStringList lst = dir.entryList("*.keytab"); + + for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) { + QFile file(path + "/" + *it); + KeyTrans* sc = KeyTrans::fromDevice(*it, file); + if (sc) { + sc->addKeyTrans(); + } + } + +} + +// Debugging material ----------------------------------------------------------- +/* +void TestTokenizer(QBuffer &buf) +{ + // opening sequence + + buf.open(IO_ReadOnly); + cc = buf.getch(); + lineno = 1; + + // Test tokenizer + + while (getSymbol(buf)) ReportToken(); + + buf.close(); +} + +void test() +{ + // Opening sequence + + QCString txt = +#include "default.keytab.h" + ; + QBuffer buf(txt); + if (0) TestTokenizer(buf); + if (1) { KeyTrans kt; kt.scanTable(buf); } +} +*/ diff --git a/core/apps/embeddedkonsole/keytrans.h b/core/apps/embeddedkonsole/keytrans.h new file mode 100644 index 0000000..ef6ed15 --- a/dev/null +++ b/core/apps/embeddedkonsole/keytrans.h @@ -0,0 +1,93 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [keytrans.h] X Terminal Emulation */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +#ifndef KEYTRANS_H +#define KEYTRANS_H + +#include +#include +#include + +#define BITS_NewLine 0 +#define BITS_BsHack 1 +#define BITS_Ansi 2 +#define BITS_AppCuKeys 3 +#define BITS_Control 4 +#define BITS_Shift 5 +#define BITS_Alt 6 +#define BITS_COUNT 7 + +#define CMD_send 0 +#define CMD_emitSelection 1 +#define CMD_scrollPageUp 2 +#define CMD_scrollPageDown 3 +#define CMD_scrollLineUp 4 +#define CMD_scrollLineDown 5 +#define CMD_prevSession 6 +#define CMD_nextSession 7 + +#define BITS(x,v) ((((v)!=0)<<(x))) + + +class KeyTrans +{ +public: + KeyTrans(); + ~KeyTrans(); + static KeyTrans* defaultKeyTrans(); + static KeyTrans* fromFile(const char* path); + static KeyTrans* find(int numb); + static KeyTrans* find(const char* path); +public: + static int count(); + static void loadAll(); +public: + bool findEntry(int key, int bits, int* cmd, const char** txt, int* len); +private: + void addKeyTrans(); + static KeyTrans* fromDevice(QString path, QIODevice &buf); +public: + class KeyEntry + { + public: + KeyEntry(int ref, int key, int bits, int mask, int cmd, QString txt); + ~KeyEntry(); + public: + bool matches(int key, int bits, int mask); + QString text(); + public: + int ref; + private: + int key; + int bits; + int mask; + public: + int cmd; + QString txt; + }; +public: + KeyEntry* addEntry(int ref, int key, int bits, int mask, int cmd, QString txt); +private: + QList table; +public: //FIXME: we'd do better + QString hdr; + int numb; + QString path; +}; + +#endif diff --git a/core/apps/embeddedkonsole/konsole.cpp b/core/apps/embeddedkonsole/konsole.cpp new file mode 100644 index 0000000..7253baf --- a/dev/null +++ b/core/apps/embeddedkonsole/konsole.cpp @@ -0,0 +1,512 @@ +/* ---------------------------------------------------------------------- */ +/* */ +/* [main.C] Konsole */ +/* */ +/* ---------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole, an X terminal. */ +/* */ +/* The material contained in here more or less directly orginates from */ +/* kvt, which is copyright (c) 1996 by Matthias Ettrich */ +/* */ +/* ---------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "konsole.h" +#include "keytrans.h" + +class EKNumTabBar : public QTabBar { +public: + void numberTabs() + { + // Yes, it really is this messy. QTabWidget needs functions + // that provide acces to tabs in a sequential way. + int m=INT_MIN; + for (int i=0; i it(*tabList()); + int x=INT_MAX; + for( QTab* t; (t=it.current()); ++it ) { + int tx = t->rect().x(); + if ( txm ) { + x = tx; + left = t; + } + } + if ( left ) { + left->setText(QString::number(i+1)); + m = left->rect().x(); + } + } + } +}; + +class EKNumTabWidget : public QTabWidget { +public: + EKNumTabWidget(QWidget* parent) : QTabWidget(parent) + { + } + + void addTab(QWidget* w) + { + QTab* t = new QTab(QString::number(tabBar()->count()+1)); + QTabWidget::addTab(w,t); + } + + void removeTab(QWidget* w) + { + removePage(w); + ((EKNumTabBar*)tabBar())->numberTabs(); + } +}; + +// This could be configurable or dynamicly generated from the bash history +// file of the user +static const char *commonCmds[] = +{ + "ls ", + //"ls -la ", + "cd ", + "pwd", + //"cat", + //"less ", + //"vi ", + //"man ", + "echo ", + "set ", + //"ps", + "ps aux", + //"tar", + //"tar -zxf", + "grep ", + //"grep -i", + //"mkdir", + "cp ", + "mv ", + "rm ", + "rmdir ", + //"chmod", + //"su", +// "top", + //"find", + //"make", + //"tail", + "cardctl eject", + "ifconfig ", +// "iwconfig eth0 ", + "nc localhost 7777", + "nc localhost 7776", + //"mount /dev/hda1", + +/* + "gzip", + "gunzip", + "chgrp", + "chown", + "date", + "dd", + "df", + "dmesg", + "fuser", + "hostname", + "kill", + "killall", + "ln", + "ping", + "mount", + "more", + "sort", + "touch", + "umount", + "mknod", + "netstat", +*/ + + "exit", + NULL +}; + + +Konsole::Konsole(QWidget* parent, const char* name, WFlags fl) : + QMainWindow(parent, name, fl) +{ + QStrList args; + init("/bin/sh",args); +} + +Konsole::Konsole(const char* name, const char* _pgm, QStrList & _args, int) + : QMainWindow(0, name) +{ + init(_pgm,_args); +} + +void Konsole::init(const char* _pgm, QStrList & _args) +{ + b_scroll = TRUE; // histon; + n_keytab = 0; + n_render = 0; + + setCaption( tr("Terminal") ); + setIcon( Resource::loadPixmap( "konsole" ) ); + + Config cfg("Konsole"); + cfg.setGroup("Konsole"); + + // initialize the list of allowed fonts /////////////////////////////////// + cfont = cfg.readNumEntry("FontID", 1); + QFont f = QFont("Micro", 4, QFont::Normal); + f.setFixedPitch(TRUE); + fonts.append(new VTFont(tr("Micro"), f)); + + f = QFont("Fixed", 7, QFont::Normal); + f.setFixedPitch(TRUE); + fonts.append(new VTFont(tr("Small Fixed"), f)); + + f = QFont("Fixed", 12, QFont::Normal); + f.setFixedPitch(TRUE); + fonts.append(new VTFont(tr("Medium Fixed"), f)); + + // create terminal emulation framework //////////////////////////////////// + nsessions = 0; + tab = new EKNumTabWidget(this); + tab->setTabPosition(QTabWidget::Bottom); + connect(tab, SIGNAL(currentChanged(QWidget*)), this, SLOT(switchSession(QWidget*))); + + // create terminal toolbar //////////////////////////////////////////////// + setToolBarsMovable( FALSE ); + QPEToolBar *menuToolBar = new QPEToolBar( this ); + menuToolBar->setHorizontalStretchable( TRUE ); + + QPEMenuBar *menuBar = new QPEMenuBar( menuToolBar ); + + fontList = new QPopupMenu( this ); + for(uint i = 0; i < fonts.count(); i++) { + VTFont *fnt = fonts.at(i); + fontList->insertItem(fnt->getName(), i); + } + fontChanged(cfont); + + connect( fontList, SIGNAL( activated(int) ), this, SLOT( fontChanged(int) )); + + menuBar->insertItem( tr("Font"), fontList ); + + QPEToolBar *toolbar = new QPEToolBar( this ); + + QAction *a; + + // Button Commands + a = new QAction( tr("New"), Resource::loadPixmap( "konsole" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( newSession() ) ); a->addTo( toolbar ); + a = new QAction( tr("Enter"), Resource::loadPixmap( "konsole/enter" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( hitEnter() ) ); a->addTo( toolbar ); + a = new QAction( tr("Space"), Resource::loadPixmap( "konsole/space" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( hitSpace() ) ); a->addTo( toolbar ); + a = new QAction( tr("Tab"), Resource::loadPixmap( "konsole/tab" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( hitTab() ) ); a->addTo( toolbar ); + a = new QAction( tr("Up"), Resource::loadPixmap( "konsole/up" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( hitUp() ) ); a->addTo( toolbar ); + a = new QAction( tr("Down"), Resource::loadPixmap( "konsole/down" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( hitDown() ) ); a->addTo( toolbar ); + a = new QAction( tr("Paste"), Resource::loadPixmap( "paste" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( hitPaste() ) ); a->addTo( toolbar ); +/* + a = new QAction( tr("Up"), Resource::loadPixmap( "up" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( hitUp() ) ); a->addTo( toolbar ); + a = new QAction( tr("Down"), Resource::loadPixmap( "down" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( hitDown() ) ); a->addTo( toolbar ); +*/ + + QPEToolBar *secondToolBar = new QPEToolBar( this ); + secondToolBar->setHorizontalStretchable( TRUE ); + + QComboBox *commonCombo = new QComboBox( secondToolBar ); +// commonCombo->setEditable( TRUE ); + for (int i = 0; commonCmds[i] != NULL; i++) + commonCombo->insertItem( commonCmds[i], i ); + connect( commonCombo, SIGNAL( activated(int) ), this, SLOT( enterCommand(int) )); + + // create applications ///////////////////////////////////////////////////// + setCentralWidget(tab); + + // load keymaps //////////////////////////////////////////////////////////// + KeyTrans::loadAll(); + for (int i = 0; i < KeyTrans::count(); i++) + { KeyTrans* s = KeyTrans::find(i); + assert( s ); + } + + se_pgm = _pgm; + se_args = _args; + + // read and apply default values /////////////////////////////////////////// + resize(321, 321); // Dummy. + QSize currentSize = size(); + if (currentSize != size()) + defaultSize = size(); +} + +void Konsole::show() +{ + if ( !nsessions ) { + newSession(); + } + QMainWindow::show(); +} + +void Konsole::initSession(const char*, QStrList &) +{ + QMainWindow::show(); +} + +Konsole::~Konsole() +{ + while (nsessions > 0) { + doneSession(getTe()->currentSession, 0); + } + + Config cfg("Konsole"); + cfg.setGroup("Konsole"); + cfg.writeEntry("FontID", cfont); +} + +void Konsole::fontChanged(int f) +{ + VTFont* font = fonts.at(f); + if (font != 0) { + for(uint i = 0; i < fonts.count(); i++) { + fontList->setItemChecked(i, (i == (uint) f) ? TRUE : FALSE); + } + + cfont = f; + + TEWidget* te = getTe(); + if (te != 0) { + te->setVTFont(font->getFont()); + } + } +} + +void Konsole::enterCommand(int c) +{ + TEWidget* te = getTe(); + if (te != 0) { + QString text = commonCmds[c]; + te->emitText(text); + } +} + +void Konsole::hitEnter() +{ + TEWidget* te = getTe(); + if (te != 0) { + te->emitText(QString("\r")); + } +} + +void Konsole::hitSpace() +{ + TEWidget* te = getTe(); + if (te != 0) { + te->emitText(QString(" ")); + } +} + +void Konsole::hitTab() +{ + TEWidget* te = getTe(); + if (te != 0) { + te->emitText(QString("\t")); + } +} + +void Konsole::hitPaste() +{ + TEWidget* te = getTe(); + if (te != 0) { + te->pasteClipboard(); + } +} + +void Konsole::hitUp() +{ + TEWidget* te = getTe(); + if (te != 0) { + QKeyEvent ke( QKeyEvent::KeyPress, Qt::Key_Up, 0, 0); + QApplication::sendEvent( te, &ke ); + } +} + +void Konsole::hitDown() +{ + TEWidget* te = getTe(); + if (te != 0) { + QKeyEvent ke( QKeyEvent::KeyPress, Qt::Key_Down, 0, 0); + QApplication::sendEvent( te, &ke ); + } +} + +/** + This function calculates the size of the external widget + needed for the internal widget to be + */ +QSize Konsole::calcSize(int columns, int lines) { + TEWidget* te = getTe(); + if (te != 0) { + QSize size = te->calcSize(columns, lines); + return size; + } else { + QSize size; + return size; + } +} + +/** + sets application window to a size based on columns X lines of the te + guest widget. Call with (0,0) for setting default size. +*/ + +void Konsole::setColLin(int columns, int lines) +{ + if ((columns==0) || (lines==0)) + { + if (defaultSize.isEmpty()) // not in config file : set default value + { + defaultSize = calcSize(80,24); + // notifySize(24,80); // set menu items (strange arg order !) + } + resize(defaultSize); + } else { + resize(calcSize(columns, lines)); + // notifySize(lines,columns); // set menu items (strange arg order !) + } +} + +/* +void Konsole::setFont(int fontno) +{ + QFont f; + if (fontno == 0) + f = defaultFont = QFont( "Helvetica", 12 ); + else + if (fonts[fontno][0] == '-') + f.setRawName( fonts[fontno] ); + else + { + f.setFamily(fonts[fontno]); + f.setRawMode( TRUE ); + } + if ( !f.exactMatch() && fontno != 0) + { + QString msg = i18n("Font `%1' not found.\nCheck README.linux.console for help.").arg(fonts[fontno]); + QMessageBox(this, msg); + return; + } + if (se) se->setFontNo(fontno); + te->setVTFont(f); + n_font = fontno; +} +*/ + +// --| color selection |------------------------------------------------------- + +void Konsole::changeColumns(int columns) +{ + TEWidget* te = getTe(); + if (te != 0) { + setColLin(columns,te->Lines()); + te->update(); + } +} + +//FIXME: If a child dies during session swap, +// this routine might be called before +// session swap is completed. + +void Konsole::doneSession(TESession*, int ) +{ + TEWidget *te = getTe(); + if (te != 0) { + te->currentSession->setConnect(FALSE); + tab->removeTab(te); + delete te->currentSession; + delete te; + nsessions--; + } + + if (nsessions == 0) { + close(); + } +} + + +void Konsole::newSession() { + TEWidget* te = new TEWidget(tab); + te->setBackgroundMode(PaletteBase); + te->setVTFont(fonts.at(cfont)->getFont()); + tab->addTab(te); + TESession* se = new TESession(this, te, se_pgm, se_args, "xterm"); + te->currentSession = se; + connect( se, SIGNAL(done(TESession*,int)), this, SLOT(doneSession(TESession*,int)) ); + se->run(); + se->setConnect(TRUE); + se->setHistory(b_scroll); + tab->setCurrentPage(nsessions); + nsessions++; +} + +TEWidget* Konsole::getTe() { + if (nsessions) { + return (TEWidget *) tab->currentPage(); + } else { + return 0; + } + } + +void Konsole::switchSession(QWidget* w) { + TEWidget* te = (TEWidget *) w; + + QFont teFnt = te->getVTFont(); + for(uint i = 0; i < fonts.count(); i++) { + VTFont *fnt = fonts.at(i); + bool cf = fnt->getFont() == teFnt; + fontList->setItemChecked(i, cf); + if (cf) { + cfont = i; + } + } +} diff --git a/core/apps/embeddedkonsole/konsole.h b/core/apps/embeddedkonsole/konsole.h new file mode 100644 index 0000000..819ea5d --- a/dev/null +++ b/core/apps/embeddedkonsole/konsole.h @@ -0,0 +1,125 @@ +/* ----------------------------------------------------------------------- */ +/* */ +/* [konsole.h] Konsole */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole, an X terminal. */ +/* */ +/* The material contained in here more or less directly orginates from */ +/* kvt, which is copyright (c) 1996 by Matthias Ettrich */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +#ifndef KONSOLE_H +#define KONSOLE_H + + +#include +#include +#include +#include +#include +#include +#include + +#include "MyPty.h" +#include "TEWidget.h" +#include "TEmuVt102.h" +#include "session.h" + +class EKNumTabWidget; + +class Konsole : public QMainWindow +{ +Q_OBJECT + +public: + + Konsole(QWidget* parent = 0, const char* name = 0, WFlags fl = 0); + Konsole(const char * name, const char* pgm, QStrList & _args, int histon); + ~Konsole(); + void setColLin(int columns, int lines); + + void show(); + +private slots: + void doneSession(TESession*,int); + void changeColumns(int); + void fontChanged(int); + void enterCommand(int); + void hitEnter(); + void hitSpace(); + void hitTab(); + void hitPaste(); + void hitUp(); + void hitDown(); + void switchSession(QWidget *); + void newSession(); + +private: + void init(const char* _pgm, QStrList & _args); + void initSession(const char* _pgm, QStrList & _args); + void runSession(TESession* s); + void setColorPixmaps(); + void setHistory(bool); + QSize calcSize(int columns, int lines); + TEWidget* getTe(); + +private: + class VTFont + { + public: + VTFont(QString name, QFont& font) + { + this->name = name; + this->font = font; + } + + QFont& getFont() + { + return font; + } + + QString getName() + { + return name; + } + + private: + QString name; + QFont font; + }; + + EKNumTabWidget* tab; + int nsessions; + QList fonts; + int cfont; + QCString se_pgm; + QStrList se_args; + + QPopupMenu* fontList; + + // history scrolling I think + bool b_scroll; + + int n_keytab; + int n_scroll; + int n_render; + QString pmPath; // pixmap path + QString dropText; + QFont defaultFont; + QSize defaultSize; + +}; + +#endif + diff --git a/core/apps/embeddedkonsole/main.cpp b/core/apps/embeddedkonsole/main.cpp new file mode 100644 index 0000000..e3ba346 --- a/dev/null +++ b/core/apps/embeddedkonsole/main.cpp @@ -0,0 +1,60 @@ +/* ---------------------------------------------------------------------- */ +/* */ +/* [main.C] Konsole */ +/* */ +/* ---------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole, an X terminal. */ +/* */ +/* The material contained in here more or less directly orginates from */ +/* kvt, which is copyright (c) 1996 by Matthias Ettrich */ +/* */ +/* ---------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +#include "konsole.h" + +#include + +#include + +#include +#include +#include + + +/* --| main |------------------------------------------------------ */ +int main(int argc, char* argv[]) +{ + setuid(getuid()); setgid(getgid()); // drop privileges + + QPEApplication a( argc, argv ); + +#ifdef FAKE_CTRL_AND_ALT + QPEApplication::grabKeyboard(); // for CTRL and ALT +#endif + + QStrList tmp; + const char* shell = getenv("SHELL"); + if (shell == NULL || *shell == '\0') + shell = "/bin/sh"; + + // sh is completely broken on familiar. Let's try to get something better + if ( qstrcmp( shell, "/bin/shell" ) == 0 && QFile::exists( "/bin/bash" ) ) + shell = "/bin/bash"; + + putenv((char*)"COLORTERM="); // to trigger mc's color detection + + Konsole m( "test", shell, tmp, TRUE ); + m.setCaption( Konsole::tr("Terminal") ); + a.showMainWidget( &m ); + + return a.exec(); +} diff --git a/core/apps/embeddedkonsole/qpe-embeddedkonsole.control b/core/apps/embeddedkonsole/qpe-embeddedkonsole.control new file mode 100644 index 0000000..9b7c355 --- a/dev/null +++ b/core/apps/embeddedkonsole/qpe-embeddedkonsole.control @@ -0,0 +1,9 @@ +Files: bin/embeddedkonsole apps/Applications/embeddedkonsole.desktop pics/konsole etc/keytabs/* +Priority: optional +Section: qpe/applications +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-4 +Depends: qpe-base ($QPE_VERSION), ptydevs +Description: KDE's konsole (shell terminal) + Ported to the Qtopia environment. diff --git a/core/apps/embeddedkonsole/session.cpp b/core/apps/embeddedkonsole/session.cpp new file mode 100644 index 0000000..520af86 --- a/dev/null +++ b/core/apps/embeddedkonsole/session.cpp @@ -0,0 +1,157 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ +#include "session.h" +#include +// #include + +#include + +#define HERE fprintf(stderr,"%s(%d): here\n",__FILE__,__LINE__) + +/*! \class TESession + + Sessions are combinations of TEPTy and Emulations. + + The stuff in here does not belong to the terminal emulation framework, + but to main.C. It serves it's duty by providing a single reference + to TEPTy/Emulation pairs. In fact, it is only there to demonstrate one + of the abilities of the framework - multible sessions. +*/ + +TESession::TESession(QMainWindow* main, TEWidget* te, const char* _pgm, QStrList & _args, const char *_term) : schema_no(0), font_no(3), pgm(_pgm), args(_args) +{ + // sh = new TEPty(); + sh = new MyPty(); + em = new TEmuVt102(te); + + term = _term; + + sh->setSize(te->Lines(),te->Columns()); // not absolutely nessesary + QObject::connect( sh,SIGNAL(block_in(const char*,int)), + em,SLOT(onRcvBlock(const char*,int)) ); + QObject::connect( em,SIGNAL(ImageSizeChanged(int,int)), + sh,SLOT(setSize(int,int))); + + // 'main' should do those connects itself, somehow. + // These aren't KTMW's slots, but konsole's.(David) + +/* + QObject::connect( em,SIGNAL(ImageSizeChanged(int,int)), + main,SLOT(notifySize(int,int))); +*/ + QObject::connect( em,SIGNAL(sndBlock(const char*,int)), + sh,SLOT(send_bytes(const char*,int)) ); + QObject::connect( em,SIGNAL(changeColumns(int)), + main,SLOT(changeColumns(int)) ); +/* + QObject::connect( em,SIGNAL(changeTitle(int, const QString&)), + main,SLOT(changeTitle(int, const QString&)) ); +*/ + QObject::connect( sh,SIGNAL(done(int)), this,SLOT(done(int)) ); +} + + + +void TESession::run() +{ + //kdDebug() << "Running the session!" << pgm << "\n"; + sh->run(pgm,args,term.data(),FALSE); +} + +void TESession::kill(int ) // signal) +{ +// sh->kill(signal); +} + +TESession::~TESession() +{ + QObject::disconnect( sh, SIGNAL( done( int ) ), + this, SLOT( done( int ) ) ); + delete em; + delete sh; +} + +void TESession::setConnect(bool c) +{ + em->setConnect(c); +} + +void TESession::done(int status) +{ + emit done(this,status); +} + +void TESession::terminate() +{ + delete this; +} + +TEmulation* TESession::getEmulation() +{ + return em; +} + +// following interfaces might be misplaced /// + +int TESession::schemaNo() +{ + return schema_no; +} + +int TESession::keymap() +{ + return keymap_no; +} + +int TESession::fontNo() +{ + return font_no; +} + +const char* TESession::emuName() +{ + return term.data(); +} + +void TESession::setSchemaNo(int sn) +{ + schema_no = sn; +} + +void TESession::setKeymapNo(int kn) +{ + keymap_no = kn; + em->setKeytrans(kn); +} + +void TESession::setFontNo(int fn) +{ + font_no = fn; +} + +void TESession::setTitle(const QString& title) +{ + this->title = title; +} + +const QString& TESession::Title() +{ + return title; +} + +void TESession::setHistory(bool on) +{ + em->setHistory( on ); +} + +bool TESession::history() +{ + return em->history(); +} + +// #include "session.moc" diff --git a/core/apps/embeddedkonsole/session.h b/core/apps/embeddedkonsole/session.h new file mode 100644 index 0000000..4a61569 --- a/dev/null +++ b/core/apps/embeddedkonsole/session.h @@ -0,0 +1,93 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [session.h] Testbed for TE framework */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle */ +/* */ +/* This file is part of Konsole, an X terminal. */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland */ +/* */ +/* -------------------------------------------------------------------------- */ + +#ifndef SESSION_H +#define SESSION_H + +#include +#include +#include + +#include "MyPty.h" +#include "TEWidget.h" +#include "TEmuVt102.h" + +class TESession : public QObject +{ Q_OBJECT + +public: + + TESession(QMainWindow* main, TEWidget* w, + const char* pgm, QStrList & _args, + const char* term); + ~TESession(); + +public: + + void setConnect(bool r); + TEmulation* getEmulation(); // to control emulation + bool isSecure(); + +public: + + int schemaNo(); + int fontNo(); + const char* emuName(); + const QString& Title(); + bool history(); + int keymap(); + + void setHistory(bool on); + void setSchemaNo(int sn); + void setKeymapNo(int kn); + void setFontNo(int fn); + void setTitle(const QString& title); + void kill(int signal); + +public slots: + + void run(); + void done(int status); + void terminate(); + +signals: + + void done(TESession*, int); + +private: + + // TEPty* sh; + MyPty* sh; + TEWidget* te; + TEmulation* em; + + //FIXME: using the indices here + // is propably very bad. We should + // use a persistent reference instead. + int schema_no; + int font_no; + int keymap_no; + QString title; + + const char* pgm; + QStrList args; + + QCString term; +}; + +#endif diff --git a/core/apps/helpbrowser/.cvsignore b/core/apps/helpbrowser/.cvsignore new file mode 100644 index 0000000..6fe2396 --- a/dev/null +++ b/core/apps/helpbrowser/.cvsignore @@ -0,0 +1,2 @@ +moc_* +Makefile diff --git a/core/apps/helpbrowser/Makefile.in b/core/apps/helpbrowser/Makefile.in new file mode 100644 index 0000000..8f0ce0e --- a/dev/null +++ b/core/apps/helpbrowser/Makefile.in @@ -0,0 +1,119 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = $(QPEDIR)/bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = helpbrowser +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = helpbrowser.h +SOURCES = helpbrowser.cpp \ + main.cpp +OBJECTS = helpbrowser.o \ + main.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = moc_helpbrowser.cpp +OBJMOC = moc_helpbrowser.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake helpbrowser.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +helpbrowser.o: helpbrowser.cpp \ + helpbrowser.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/global.h \ + $(QPEDIR)/include/qpe/qpemenubar.h \ + $(QPEDIR)/include/qpe/qpetoolbar.h + +main.o: main.cpp \ + helpbrowser.h \ + $(QPEDIR)/include/qpe/qpeapplication.h + +moc_helpbrowser.o: moc_helpbrowser.cpp \ + helpbrowser.h + +moc_helpbrowser.cpp: helpbrowser.h + $(MOC) helpbrowser.h -o moc_helpbrowser.cpp + + diff --git a/core/apps/helpbrowser/helpbrowser.cpp b/core/apps/helpbrowser/helpbrowser.cpp new file mode 100644 index 0000000..d32fc0b --- a/dev/null +++ b/core/apps/helpbrowser/helpbrowser.cpp @@ -0,0 +1,227 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "helpbrowser.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +HelpBrowser::HelpBrowser( QWidget* parent, const char *name, WFlags f ) + : QMainWindow( parent, name, f ), + selectedURL() +{ + init( "index.html" ); +} + +void HelpBrowser::init( const QString& _home ) +{ + setIcon( Resource::loadPixmap( "help_icon" ) ); + + browser = new QTextBrowser( this ); + browser->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + connect( browser, SIGNAL( textChanged() ), + this, SLOT( textChanged() ) ); + + setCentralWidget( browser ); + setToolBarsMovable( FALSE ); + + if ( !_home.isEmpty() ) + browser->setSource( _home ); + + QPEToolBar* toolbar = new QPEToolBar( this ); + toolbar->setHorizontalStretchable( TRUE ); + QPEMenuBar *menu = new QPEMenuBar( toolbar ); + + toolbar = new QPEToolBar( this ); + // addToolBar( toolbar, "Toolbar"); + + //QPopupMenu* go = new QPopupMenu( this ); + backAction = new QAction( tr( "Backward" ), Resource::loadIconSet( "back" ), QString::null, 0, this, 0 ); + connect( backAction, SIGNAL( activated() ), browser, SLOT( backward() ) ); + connect( browser, SIGNAL( backwardAvailable( bool ) ), + backAction, SLOT( setEnabled( bool ) ) ); + //backAction->addTo( go ); + backAction->addTo( toolbar ); + backAction->setEnabled( FALSE ); + + forwardAction = new QAction( tr( "Forward" ), Resource::loadIconSet( "forward" ), QString::null, 0, this, 0 ); + connect( forwardAction, SIGNAL( activated() ), browser, SLOT( forward() ) ); + connect( browser, SIGNAL( forwardAvailable( bool ) ), + forwardAction, SLOT( setEnabled( bool ) ) ); + //forwardAction->addTo( go ); + forwardAction->addTo( toolbar ); + forwardAction->setEnabled( FALSE ); + + QAction *a = new QAction( tr( "Home" ), Resource::loadPixmap( "home" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), browser, SLOT( home() ) ); + //a->addTo( go ); + a->addTo( toolbar ); + + bookm = new QPopupMenu( this ); + bookm->insertItem( tr( "Add Bookmark" ), this, SLOT( addBookmark() ) ); + bookm->insertItem( tr( "Remove from Bookmarks" ), this, SLOT( removeBookmark() ) ); + bookm->insertSeparator(); + connect( bookm, SIGNAL( activated( int ) ), + this, SLOT( bookmChosen( int ) ) ); + + readBookmarks(); + + //menu->insertItem( tr("Go"), go ); + menu->insertItem( tr( "Bookmarks" ), bookm ); + + resize( 240, 300 ); + browser->setFocus(); + + connect( qApp, SIGNAL(appMessage(const QCString&, const QByteArray&)), + this, SLOT(appMessage(const QCString&, const QByteArray&)) ); +} + +void HelpBrowser::appMessage(const QCString& msg, const QByteArray& data) +{ + if ( msg == "showFile(QString)" ) { + QDataStream ds(data,IO_ReadOnly); + QString fn; + ds >> fn; + setDocument( fn ); + } +} + +void HelpBrowser::setDocument( const QString &doc ) +{ + if ( !doc.isEmpty() ) + browser->setSource( doc ); + raise(); +} + + +void HelpBrowser::textChanged() +{ + if ( browser->documentTitle().isNull() ) + setCaption( tr("Help Browser") ); + else + setCaption( browser->documentTitle() ) ; + + selectedURL = caption(); +} + +HelpBrowser::~HelpBrowser() +{ + QStringList bookmarks; + QMap::Iterator it2 = mBookmarks.begin(); + for ( ; it2 != mBookmarks.end(); ++it2 ) + bookmarks.append( (*it2).name + "=" + (*it2).file ); + + QFile f2( Global::applicationFileName("helpbrowser", "bookmarks") ); + if ( f2.open( IO_WriteOnly ) ) { + QDataStream s2( &f2 ); + s2 << bookmarks; + f2.close(); + } +} + +void HelpBrowser::pathSelected( const QString &_path ) +{ + browser->setSource( _path ); +} + +void HelpBrowser::readBookmarks() +{ + QString file = Global::applicationFileName("helpbrowser", "bookmarks"); + if ( QFile::exists( file ) ) { + QStringList bookmarks; + QFile f( file ); + if ( f.open( IO_ReadOnly ) ) { + QDataStream s( &f ); + s >> bookmarks; + f.close(); + } + QStringList::Iterator it = bookmarks.begin(); + for ( ; it != bookmarks.end(); ++it ) { + Bookmark b; + QString current = *it; + int equal = current.find( "=" ); + if ( equal < 1 || equal == (int)current.length() - 1 ) + continue; + b.name = current.left( equal ); + b.file = current.mid( equal + 1 ); + mBookmarks[ bookm->insertItem( b.name ) ] = b; + } + } +} + +void HelpBrowser::bookmChosen( int i ) +{ + if ( mBookmarks.contains( i ) ) + browser->setSource( mBookmarks[ i ].file ); +} + +void HelpBrowser::addBookmark() +{ + Bookmark b; + b.name = browser->documentTitle(); + b.file = browser->source(); + if (b.name.isEmpty() ) { + b.name = b.file.left( b.file.length() - 5 ); // remove .html + } + QMap::Iterator it; + for( it = mBookmarks.begin(); it != mBookmarks.end(); ++it ) + if ( (*it).file == b.file ) return; + mBookmarks[ bookm->insertItem( b.name ) ] = b; +} + +void HelpBrowser::removeBookmark() +{ + QString file = browser->source(); + QMap::Iterator it = mBookmarks.begin(); + for( ; it != mBookmarks.end(); ++it ) + if ( (*it).file == file ) { + bookm->removeItem( it.key() ); + mBookmarks.remove( it ); + break; + } +} diff --git a/core/apps/helpbrowser/helpbrowser.h b/core/apps/helpbrowser/helpbrowser.h new file mode 100644 index 0000000..2f7153a --- a/dev/null +++ b/core/apps/helpbrowser/helpbrowser.h @@ -0,0 +1,69 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef HELPWINDOW_H +#define HELPWINDOW_H + +#include +#include +#include +#include + +class QPopupMenu; +class QAction; + +class HelpBrowser : public QMainWindow +{ + Q_OBJECT +public: + HelpBrowser( QWidget* parent = 0, const char *name=0, WFlags f=0 ); + ~HelpBrowser(); + +public slots: + void setDocument( const QString &doc ); + +private slots: + void appMessage(const QCString& msg, const QByteArray& data); + void textChanged(); + + void pathSelected( const QString & ); + void bookmChosen( int ); + void addBookmark(); + void removeBookmark(); + +private: + void init( const QString & ); + void readBookmarks(); + + QTextBrowser* browser; + QAction *backAction; + QAction *forwardAction; + QString selectedURL; + struct Bookmark { + QString name; + QString file; + }; + QMap mBookmarks; + QMenuBar *menu; + QPopupMenu *bookm; +}; + +#endif + diff --git a/core/apps/helpbrowser/helpbrowser.pro b/core/apps/helpbrowser/helpbrowser.pro new file mode 100644 index 0000000..43230f1 --- a/dev/null +++ b/core/apps/helpbrowser/helpbrowser.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +CONFIG = qt warn_on release +DESTDIR = $(QPEDIR)/bin +HEADERS = helpbrowser.h +SOURCES = helpbrowser.cpp \ + main.cpp +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe +INTERFACES = + +TRANSLATIONS = ../i18n/de/helpbrowser.ts diff --git a/core/apps/helpbrowser/main.cpp b/core/apps/helpbrowser/main.cpp new file mode 100644 index 0000000..1cb10b7 --- a/dev/null +++ b/core/apps/helpbrowser/main.cpp @@ -0,0 +1,34 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "helpbrowser.h" + +#include + +int main( int argc, char ** argv ) +{ + QPEApplication a( argc, argv ); + + HelpBrowser mw; + mw.setCaption( HelpBrowser::tr("HelpBrowser") ); + a.showMainDocumentWidget( &mw ); + + return a.exec(); +} diff --git a/core/apps/helpbrowser/qpe-helpbrowser.control b/core/apps/helpbrowser/qpe-helpbrowser.control new file mode 100644 index 0000000..b6e3404 --- a/dev/null +++ b/core/apps/helpbrowser/qpe-helpbrowser.control @@ -0,0 +1,10 @@ +Files: bin/helpbrowser apps/Applications/helpbrowser.desktop docs +Priority: optional +Section: qpe/applications +Maintainer: Warwick Allison +Architecture: arm +Arch: iPAQ +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: Browse HTML help documents + The HTML help browser for the Qtopia environment. diff --git a/core/apps/qcop/.cvsignore b/core/apps/qcop/.cvsignore new file mode 100644 index 0000000..edfa921 --- a/dev/null +++ b/core/apps/qcop/.cvsignore @@ -0,0 +1,3 @@ +moc_* +*.moc +Makefile diff --git a/core/apps/qcop/Makefile.in b/core/apps/qcop/Makefile.in new file mode 100644 index 0000000..0a12320 --- a/dev/null +++ b/core/apps/qcop/Makefile.in @@ -0,0 +1,102 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = qcop +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = +SOURCES = main.cpp +OBJECTS = main.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = +OBJMOC = + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake qcop.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +main.o: main.cpp \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h + + diff --git a/core/apps/qcop/main.cpp b/core/apps/qcop/main.cpp new file mode 100644 index 0000000..73db0f6 --- a/dev/null +++ b/core/apps/qcop/main.cpp @@ -0,0 +1,85 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +static void usage() +{ + fprintf( stderr, "Usage: qcop channel command [parameters]\n" ); +} + +static void syntax( const QString &where, const QString &what ) +{ + fprintf( stderr, "Syntax error in %s: %s\n", where.latin1(), what.latin1() ); + exit(1); +} + +int main( int argc, char *argv[] ) +{ + QApplication app( argc, argv ); + + if ( argc < 3 ) { + usage(); + exit(1); + } + + QString channel = argv[1]; + QString command = argv[2]; + command.stripWhiteSpace(); + + int paren = command.find( "(" ); + if ( paren <= 0 ) + syntax( "command", command ); + + QString params = command.mid( paren + 1 ); + if ( params[params.length()-1] != ')' ) + syntax( "command", command ); + + params.truncate( params.length()-1 ); + QCopEnvelope env(channel.latin1(), command.latin1()); + + int argIdx = 3; + + QStringList paramList = QStringList::split( ",", params ); + QStringList::Iterator it; + for ( it = paramList.begin(); it != paramList.end(); ++it ) { + QString arg = argv[argIdx]; + if ( *it == "QString" ) { + env << arg; + } else if ( *it == "int" ) { + env << arg.toInt(); + } else { + syntax( "paramter type", *it ); + } + argIdx++; + } + + QTimer::singleShot( 0, &app, SLOT(quit()) ); + return app.exec(); +} + diff --git a/core/apps/qcop/qcop.pro b/core/apps/qcop/qcop.pro new file mode 100644 index 0000000..b52bfd8 --- a/dev/null +++ b/core/apps/qcop/qcop.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +CONFIG = qt warn_on release +DESTDIR = ../bin +HEADERS = +SOURCES = main.cpp +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe +INTERFACES = +TARGET = qcop diff --git a/core/apps/qcop/qpe-qcop.control b/core/apps/qcop/qpe-qcop.control new file mode 100644 index 0000000..60107c4 --- a/dev/null +++ b/core/apps/qcop/qpe-qcop.control @@ -0,0 +1,9 @@ +Files: bin/qcop +Priority: required +Section: qpe/system +Maintainer: Martin Jones +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qt-embedded (>=$QTE_VERSION) +Description: Interprocess communication client + Interprocess communication client for the Qtopia environment. diff --git a/core/apps/textedit/.cvsignore b/core/apps/textedit/.cvsignore new file mode 100644 index 0000000..edfa921 --- a/dev/null +++ b/core/apps/textedit/.cvsignore @@ -0,0 +1,3 @@ +moc_* +*.moc +Makefile diff --git a/core/apps/textedit/Makefile.in b/core/apps/textedit/Makefile.in new file mode 100644 index 0000000..84542bb --- a/dev/null +++ b/core/apps/textedit/Makefile.in @@ -0,0 +1,125 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = $(QPEDIR)/bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = textedit +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = textedit.h +SOURCES = main.cpp \ + textedit.cpp +OBJECTS = main.o \ + textedit.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = moc_textedit.cpp +OBJMOC = moc_textedit.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake textedit.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +main.o: main.cpp \ + textedit.h \ + $(QPEDIR)/include/qpe/filemanager.h \ + $(QPEDIR)/include/qpe/qpeapplication.h + +textedit.o: textedit.cpp \ + textedit.h \ + $(QPEDIR)/include/qpe/filemanager.h \ + $(QPEDIR)/include/qpe/global.h \ + $(QPEDIR)/include/qpe/fileselector.h \ + $(QPEDIR)/include/qpe/applnk.h \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/qpemenubar.h \ + $(QPEDIR)/include/qpe/qpetoolbar.h + +moc_textedit.o: moc_textedit.cpp \ + textedit.h \ + $(QPEDIR)/include/qpe/filemanager.h + +moc_textedit.cpp: textedit.h + $(MOC) textedit.h -o moc_textedit.cpp + + diff --git a/core/apps/textedit/inserttable.ui b/core/apps/textedit/inserttable.ui new file mode 100644 index 0000000..09fe3c3 --- a/dev/null +++ b/core/apps/textedit/inserttable.ui @@ -0,0 +1,103 @@ + +InsertTable********************************************************************* +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +********************************************************************* + + QDialog + + name + InsertTable + + + geometry + + 0 + 0 + 165 + 79 + + + + caption + Insert Table + + + + margin + 11 + + + spacing + 6 + + + QLabel + + name + TextLabel1 + + + text + Rows: + + + + QSpinBox + + name + spinRows + + + minValue + 1 + + + value + 1 + + + + QSpinBox + + name + spinColumns + + + minValue + 1 + + + value + 1 + + + + QLabel + + name + TextLabel1_2 + + + text + Columns: + + + + + diff --git a/core/apps/textedit/main.cpp b/core/apps/textedit/main.cpp new file mode 100644 index 0000000..d0d37d2 --- a/dev/null +++ b/core/apps/textedit/main.cpp @@ -0,0 +1,35 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "textedit.h" + +#include + +int main( int argc, char **argv ) +{ + QPEApplication a( argc, argv ); + + TextEdit e; + a.showMainDocumentWidget(&e); + if ( argc == 3 && argv[1] == QCString("-f") ) + e.openFile(argv[2]); + + a.exec(); +} diff --git a/core/apps/textedit/qpe-textedit.control b/core/apps/textedit/qpe-textedit.control new file mode 100644 index 0000000..b0dad7d --- a/dev/null +++ b/core/apps/textedit/qpe-textedit.control @@ -0,0 +1,9 @@ +Files: bin/textedit apps/Applications/textedit.desktop +Priority: optional +Section: qpe/applications +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: Text Editor + The text editor for the Qtopia environment. diff --git a/core/apps/textedit/qtextedit.h b/core/apps/textedit/qtextedit.h new file mode 100644 index 0000000..b29a728 --- a/dev/null +++ b/core/apps/textedit/qtextedit.h @@ -0,0 +1,282 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QTEXTEDIT_H +#define QTEXTEDIT_H + +#include +#include +#include + +class QPainter; +class QTextDocument; +class QTextCursor; +class QKeyEvent; +class QResizeEvent; +class QMouseEvent; +class QTimer; +class QTextString; +class QVBox; +class QListBox; +class QTextCommand; +class QTextParag; +class QTextFormat; +class QFont; +class QColor; + +class QTextEdit : public QScrollView +{ + Q_OBJECT + +public: + QTextEdit( QWidget *parent, const QString &fn, bool tabify = FALSE ); + QTextEdit( QWidget *parent = 0, const char *name = 0 ); + virtual ~QTextEdit(); + +#if defined(QTEXTEDIT_OPEN_API) + QTextDocument *document() const; + QTextCursor *textCursor() const; +#endif + + QString text() const; + QString text( int parag, bool formatted = FALSE ) const; + Qt::TextFormat textFormat() const; + QString fileName() const; + + void cursorPosition( int ¶g, int &index ); + void selection( int ¶g_from, int &index_from, + int ¶g_to, int &index_to ); + virtual bool find( const QString &expr, bool cs, bool wo, bool forward = TRUE, + int *parag = 0, int *index = 0 ); + void insert( const QString &text, bool indent = FALSE, bool checkNewLine = FALSE ); + + int paragraphs() const; + int lines() const; + int linesOfParagraph( int parag ) const; + int lineOfChar( int parag, int chr ); + + bool isModified() const; + + bool italic() const; + bool bold() const; + bool underline() const; + QString family() const; + int pointSize() const; + QColor color() const; + QFont font() const; + int alignment() const; + int maxLines() const; + + const QStyleSheet* styleSheet() const; + void setStyleSheet( const QStyleSheet* styleSheet ); + + void setPaper( const QBrush& pap); + QBrush paper() const; + + void setLinkColor( const QColor& ); + QColor linkColor() const; + + void setLinkUnderline( bool ); + bool linkUnderline() const; + + void setMimeSourceFactory( const QMimeSourceFactory* factory ); + const QMimeSourceFactory* mimeSourceFactory() const; + + int heightForWidth( int w ) const; + + void append( const QString& text ); + + bool hasSelectedText() const; + QString selectedText() const; + + QString context() const; + + QString documentTitle() const; + + void scrollToAnchor( const QString& name ); + QString anchorAt(const QPoint& pos); + +public slots: + virtual void undo(); + virtual void redo(); + + virtual void cut(); + virtual void copy(); + virtual void paste(); + + virtual void indent(); + + virtual void setItalic( bool b ); + virtual void setBold( bool b ); + virtual void setUnderline( bool b ); + virtual void setFamily( const QString &f ); + virtual void setPointSize( int s ); + virtual void setColor( const QColor &c ); + virtual void setFont( const QFont &f ); + + virtual void setAlignment( int ); + + virtual void setParagType( QStyleSheetItem::DisplayMode, int listStyle ); + + virtual void setTextFormat( Qt::TextFormat f ); + virtual void setText( const QString &txt, const QString &context = QString::null ) { setText( txt, context, FALSE ); } + virtual void setText( const QString &txt, const QString &context, bool tabify ); + + virtual void load( const QString &fn ) { load( fn, FALSE ); } + virtual void load( const QString &fn, bool tabify ); + virtual void save( bool untabify = FALSE ) { save( QString::null, untabify ); } + virtual void save( const QString &fn, bool untabify = FALSE ); + + virtual void setCursorPosition( int parag, int index ); + virtual void setSelection( int parag_from, int index_from, + int parag_to, int index_to ); + + virtual void setModified( bool m ); + virtual void selectAll( bool select ); + + virtual void setMaxLines( int l ); + virtual void resetFormat(); + +signals: + void currentFontChanged( const QFont &f ); + void currentColorChanged( const QColor &c ); + void currentAlignmentChanged( int ); + void textChanged(); + void highlighted( const QString& ); + void linkClicked( const QString& ); + +protected: + void setFormat( QTextFormat *f, int flags ); + void drawContents( QPainter *p, int cx, int cy, int cw, int ch ); + void keyPressEvent( QKeyEvent *e ); + void resizeEvent( QResizeEvent *e ); + void contentsMousePressEvent( QMouseEvent *e ); + void contentsMouseMoveEvent( QMouseEvent *e ); + void contentsMouseReleaseEvent( QMouseEvent *e ); + void contentsMouseDoubleClickEvent( QMouseEvent *e ); +#ifndef QT_NO_DRAGANDDROP + void contentsDragEnterEvent( QDragEnterEvent *e ); + void contentsDragMoveEvent( QDragMoveEvent *e ); + void contentsDragLeaveEvent( QDragLeaveEvent *e ); + void contentsDropEvent( QDropEvent *e ); +#endif + bool eventFilter( QObject *o, QEvent *e ); + bool focusNextPrevChild( bool next ); +#if !defined(QTEXTEDIT_OPEN_API) + QTextDocument *document() const; + QTextCursor *textCursor() const; +#endif + +private slots: + void formatMore(); + void doResize(); + void doAutoScroll(); + void doChangeInterval(); + void blinkCursor(); + void setModified(); + void startDrag(); + +private: + enum MoveDirection { + MoveLeft, + MoveRight, + MoveUp, + MoveDown, + MoveHome, + MoveEnd, + MovePgUp, + MovePgDown + }; + enum KeyboardAction { + ActionBackspace, + ActionDelete, + ActionReturn + }; + + struct UndoRedoInfo { + enum Type { Invalid, Insert, Delete, Backspace, Return, RemoveSelected }; + UndoRedoInfo( QTextDocument *d ) : type( Invalid ), doc( d ) + { text = QString::null; id = -1; index = -1; } + void clear(); + inline bool valid() const { return !text.isEmpty() && id >= 0&& index >= 0; } + + QString text; + int id; + int index; + Type type; + QTextDocument *doc; + }; + +private: + virtual bool isReadOnly() const { return FALSE; } + virtual bool linksEnabled() const { return TRUE; } + void init(); + void ensureCursorVisible(); + void drawCursor( bool visible ); + void placeCursor( const QPoint &pos, QTextCursor *c = 0 ); + void moveCursor( int direction, bool shift, bool control ); + void moveCursor( int direction, bool control ); + void removeSelectedText(); + void doKeyboardAction( int action ); + bool doCompletion(); + void checkUndoRedoInfo( UndoRedoInfo::Type t ); + void repaintChanged(); + void updateCurrentFormat(); + void handleReadOnlyKeyEvent( QKeyEvent *e ); + void makeParagVisible( QTextParag *p ); + +private: + QTextDocument *doc; + QTextCursor *cursor; + bool drawAll; + bool mousePressed; + QTimer *formatTimer, *scrollTimer, *changeIntervalTimer, *blinkTimer, *dragStartTimer, *resizeTimer; + QTextParag *lastFormatted; + int interval; + QVBox *completionPopup; + QListBox *completionListBox; + int completionOffset; + UndoRedoInfo undoRedoInfo; + QTextFormat *currentFormat; + QPainter painter; + int currentAlignment; + bool inDoubleClick; + QPoint oldMousePos, mousePos; + QPixmap *buf_pixmap; + bool cursorVisible, blinkCursorVisible; + bool readOnly, modified, mightStartDrag; + QPoint dragStartPos; + int mLines; + bool firstResize; + QString onLink; + +}; + +inline QTextDocument *QTextEdit::document() const +{ + return doc; +} + +inline QTextCursor *QTextEdit::textCursor() const +{ + return cursor; +} + +#endif diff --git a/core/apps/textedit/textedit.cpp b/core/apps/textedit/textedit.cpp new file mode 100644 index 0000000..867625e --- a/dev/null +++ b/core/apps/textedit/textedit.cpp @@ -0,0 +1,594 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "textedit.h" + +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include //getenv + + +#if QT_VERSION < 300 + +class QpeEditor : public QMultiLineEdit +{ + // Q_OBJECT +public: + QpeEditor( QWidget *parent, const char * name = 0 ) + : QMultiLineEdit( parent, name ) {} + + //public slots: + void find( const QString &txt, bool caseSensitive, + bool backwards ); + /* +signals: + void notFound(); + void searchWrapped(); + */ + +private: + +}; + + +void QpeEditor::find ( const QString &txt, bool caseSensitive, + bool backwards ) +{ + static bool wrap = FALSE; + int line, col; + if ( wrap ) { + if ( !backwards ) + line = col = 0; + wrap = FALSE; + // emit searchWrapped(); + } else { + getCursorPosition( &line, &col ); + } + //ignore backwards for now.... + if ( !backwards ) { + for ( ; ; ) { + if ( line >= numLines() ) { + wrap = TRUE; + //emit notFound(); + break; + } + int findCol = getString( line )->find( txt, col, caseSensitive ); + if ( findCol >= 0 ) { + setCursorPosition( line, findCol, FALSE ); + col = findCol + txt.length(); + setCursorPosition( line, col, TRUE ); + + //found = TRUE; + break; + } + line++; + col = 0; + } + + } + +} + + +#else + +#error "Must make a QpeEditor that inherits QTextEdit" + +#endif + + + + +static int u_id = 1; +static int get_unique_id() +{ + return u_id++; +} + +static const int nfontsizes = 6; +static const int fontsize[nfontsizes] = {8,10,12,14,18,24}; + +TextEdit::TextEdit( QWidget *parent, const char *name, WFlags f ) + : QMainWindow( parent, name, f ), bFromDocView( FALSE ) +{ + doc = 0; + + QString lang = getenv( "LANG" ); + + setToolBarsMovable( FALSE ); + + setIcon( Resource::loadPixmap( "TextEditor" ) ); + + QPEToolBar *bar = new QPEToolBar( this ); + bar->setHorizontalStretchable( TRUE ); + menu = bar; + + QPEMenuBar *mb = new QPEMenuBar( bar ); + QPopupMenu *file = new QPopupMenu( this ); + QPopupMenu *edit = new QPopupMenu( this ); + QPopupMenu *font = new QPopupMenu( this ); + + bar = new QPEToolBar( this ); + editBar = bar; + + QAction *a = new QAction( tr( "New" ), Resource::loadPixmap( "new" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( fileNew() ) ); + a->addTo( bar ); + a->addTo( file ); + + a = new QAction( tr( "Open" ), Resource::loadPixmap( "fileopen" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( fileOpen() ) ); + a->addTo( bar ); + a->addTo( file ); + + a = new QAction( tr( "Cut" ), Resource::loadPixmap( "cut" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( editCut() ) ); + a->addTo( editBar ); + a->addTo( edit ); + + a = new QAction( tr( "Copy" ), Resource::loadPixmap( "copy" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( editCopy() ) ); + a->addTo( editBar ); + a->addTo( edit ); + + a = new QAction( tr( "Paste" ), Resource::loadPixmap( "paste" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( editPaste() ) ); + a->addTo( editBar ); + a->addTo( edit ); + + a = new QAction( tr( "Find..." ), Resource::loadPixmap( "find" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( editFind() ) ); + edit->insertSeparator(); + a->addTo( bar ); + a->addTo( edit ); + + int defsize; + bool defb, defi, wrap; + { + Config cfg("TextEdit"); + cfg.setGroup("View"); + defsize = cfg.readNumEntry("FontSize",10); + defb = cfg.readBoolEntry("Bold",FALSE); + defi = cfg.readBoolEntry("Italic",FALSE); + wrap = cfg.readBoolEntry("Wrap",TRUE); + } + + zin = new QAction( tr("Zoom in"), QString::null, 0, this, 0 ); + connect( zin, SIGNAL( activated() ), this, SLOT( zoomIn() ) ); + zin->addTo( font ); + + zout = new QAction( tr("Zoom out"), QString::null, 0, this, 0 ); + connect( zout, SIGNAL( activated() ), this, SLOT( zoomOut() ) ); + zout->addTo( font ); + + font->insertSeparator(); + +#if 0 + QAction *ba = new QAction( tr("Bold"), QString::null, 0, this, 0 ); + connect( ba, SIGNAL( toggled(bool) ), this, SLOT( setBold(bool) ) ); + ba->setToggleAction(TRUE); + ba->addTo( font ); + + QAction *ia = new QAction( tr("Italic"), QString::null, 0, this, 0 ); + connect( ia, SIGNAL( toggled(bool) ), this, SLOT( setItalic(bool) ) ); + ia->setToggleAction(TRUE); + ia->addTo( font ); + + ba->setOn(defb); + ia->setOn(defi); + + font->insertSeparator(); +#endif + + QAction *wa = new QAction( tr("Wrap lines"), QString::null, 0, this, 0 ); + connect( wa, SIGNAL( toggled(bool) ), this, SLOT( setWordWrap(bool) ) ); + wa->setToggleAction(TRUE); + wa->addTo( font ); + + mb->insertItem( tr( "File" ), file ); + mb->insertItem( tr( "Edit" ), edit ); + mb->insertItem( tr( "View" ), font ); + + searchBar = new QPEToolBar(this); + addToolBar( searchBar, "Search", QMainWindow::Top, TRUE ); + + searchBar->setHorizontalStretchable( TRUE ); + + searchEdit = new QLineEdit( searchBar, "searchEdit" ); + searchBar->setStretchableWidget( searchEdit ); + connect( searchEdit, SIGNAL( textChanged( const QString & ) ), + this, SLOT( search() ) ); + + a = new QAction( tr( "Find Next" ), Resource::loadPixmap( "next" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( findNext() ) ); + a->addTo( searchBar ); + a->addTo( edit ); + + a = new QAction( tr( "Close Find" ), Resource::loadPixmap( "close" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( findClose() ) ); + a->addTo( searchBar ); + + searchBar->hide(); + + editorStack = new QWidgetStack( this ); + setCentralWidget( editorStack ); + + searchVisible = FALSE; + + fileSelector = new FileSelector( "text/*", editorStack, "fileselector" , + TRUE, FALSE ); + fileSelector->setCategoriesVisible(TRUE); + connect( fileSelector, SIGNAL( closeMe() ), this, SLOT( showEditTools() ) ); + connect( fileSelector, SIGNAL( newSelected( const DocLnk &) ), this, SLOT( newFile( const DocLnk & ) ) ); + connect( fileSelector, SIGNAL( fileSelected( const DocLnk &) ), this, SLOT( openFile( const DocLnk & ) ) ); + fileOpen(); + + editor = new QpeEditor( editorStack ); + editorStack->addWidget( editor, get_unique_id() ); + + resize( 200, 300 ); + + setFontSize(defsize,TRUE); + wa->setOn(wrap); +} + +TextEdit::~TextEdit() +{ + save(); + + Config cfg("TextEdit"); + cfg.setGroup("View"); + QFont f = editor->font(); + cfg.writeEntry("FontSize",f.pointSize()); + cfg.writeEntry("Bold",f.bold()); + cfg.writeEntry("Italic",f.italic()); + cfg.writeEntry("Wrap",editor->wordWrap() == QMultiLineEdit::WidgetWidth); +} + +void TextEdit::zoomIn() +{ + setFontSize(editor->font().pointSize()+1,FALSE); +} + +void TextEdit::zoomOut() +{ + setFontSize(editor->font().pointSize()-1,TRUE); +} + + +void TextEdit::setFontSize(int sz, bool round_down_not_up) +{ + int s=10; + for (int i=0; i sz ) { + s = fontsize[i]; + break; + } + } + } + + QFont f = editor->font(); + f.setPointSize(s); + editor->setFont(f); + + zin->setEnabled(s != fontsize[nfontsizes-1]); + zout->setEnabled(s != fontsize[0]); +} + +void TextEdit::setBold(bool y) +{ + QFont f = editor->font(); + f.setBold(y); + editor->setFont(f); +} + +void TextEdit::setItalic(bool y) +{ + QFont f = editor->font(); + f.setItalic(y); + editor->setFont(f); +} + +void TextEdit::setWordWrap(bool y) +{ + editor->setWordWrap(y ? QMultiLineEdit::WidgetWidth : QMultiLineEdit::NoWrap ); +} + +void TextEdit::fileNew() +{ + save(); + newFile(DocLnk()); +} + +void TextEdit::fileOpen() +{ + if ( !save() ) { + if ( QMessageBox::critical( this, tr( "Out of space" ), + tr( "Text Editor was unable to\n" + "save your changes.\n" + "Free some space and try again.\n" + "\nContinue anyway?" ), + QMessageBox::Yes|QMessageBox::Escape, + QMessageBox::No|QMessageBox::Default ) + != QMessageBox::Yes ) + return; + else { + delete doc; + doc = 0; + } + } + menu->hide(); + editBar->hide(); + searchBar->hide(); + clearWState (WState_Reserved1 ); + editorStack->raiseWidget( fileSelector ); + fileSelector->reread(); + updateCaption(); +} + + +#if 0 +void TextEdit::slotFind() +{ + FindDialog frmFind( "Text Editor", this ); + connect( &frmFind, SIGNAL(signalFindClicked(const QString &, bool, bool, int)), + editor, SLOT(slotDoFind( const QString&,bool,bool))); + + //case sensitive, backwards, [category] + + + connect( editor, SIGNAL(notFound()), + &frmFind, SLOT(slotNotFound()) ); + connect( editor, SIGNAL(searchWrapped()), + &frmFind, SLOT(slotWrapAround()) ); + + frmFind.exec(); + + +} +#endif + +void TextEdit::fileRevert() +{ + clear(); + fileOpen(); +} + +void TextEdit::editCut() +{ +#ifndef QT_NO_CLIPBOARD + editor->cut(); +#endif +} + +void TextEdit::editCopy() +{ +#ifndef QT_NO_CLIPBOARD + editor->copy(); +#endif +} + +void TextEdit::editPaste() +{ +#ifndef QT_NO_CLIPBOARD + editor->paste(); +#endif +} + +void TextEdit::editFind() +{ + searchBar->show(); + searchVisible = TRUE; + searchEdit->setFocus(); +} + +void TextEdit::findNext() +{ + editor->find( searchEdit->text(), FALSE, FALSE ); + +} + +void TextEdit::findClose() +{ + searchVisible = FALSE; + searchBar->hide(); +} + +void TextEdit::search() +{ + editor->find( searchEdit->text(), FALSE, FALSE ); +} + +void TextEdit::newFile( const DocLnk &f ) +{ + DocLnk nf = f; + nf.setType("text/plain"); + clear(); + editorStack->raiseWidget( editor ); + setWState (WState_Reserved1 ); + editor->setFocus(); + doc = new DocLnk(nf); + updateCaption(); +} + +void TextEdit::openFile( const QString &f ) +{ + bFromDocView = TRUE; + DocLnk nf; + nf.setType("text/plain"); + nf.setFile(f); + openFile(nf); + showEditTools(); + // Show filename in caption + QString name = f; + int sep = name.findRev( '/' ); + if ( sep > 0 ) + name = name.mid( sep+1 ); + updateCaption( name ); +} + +void TextEdit::openFile( const DocLnk &f ) +{ + clear(); + FileManager fm; + QString txt; + if ( !fm.loadFile( f, txt ) ) { + // ####### could be a new file + //qDebug( "Cannot open file" ); + //return; + } + fileNew(); + if ( doc ) + delete doc; + doc = new DocLnk(f); + editor->setText(txt); + editor->setEdited(FALSE); + updateCaption(); +} + +void TextEdit::showEditTools() +{ + if ( !doc ) + close(); + fileSelector->hide(); + menu->show(); + editBar->show(); + if ( searchVisible ) + searchBar->show(); + updateCaption(); +} + +bool TextEdit::save() +{ + // case of nothing to save... + if ( !doc ) + return true; + if ( !editor->edited() ) { + delete doc; + doc = 0; + return true; + } + + QString rt = editor->text(); + + if ( doc->name().isEmpty() ) { + QString pt = rt.simplifyWhiteSpace(); + int i = pt.find( ' ' ); + QString docname = pt; + if ( i > 0 ) + docname = pt.left( i ); + // remove "." at the beginning + while( docname.startsWith( "." ) ) + docname = docname.mid( 1 ); + docname.replace( QRegExp("/"), "_" ); + // cut the length. filenames longer than that don't make sense and something goes wrong when they get too long. + if ( docname.length() > 40 ) + docname = docname.left(40); + if ( docname.isEmpty() ) + docname = "Empty Text"; + doc->setName(docname); + + // append .txt to the file name + if ( doc->file().find(".txt") == -1 ) { + QString file = doc->file() + ".txt"; + doc->setFile( file ); + } + } + + + FileManager fm; + if ( !fm.saveFile( *doc, rt ) ) { + return false; + } + delete doc; + doc = 0; + editor->setEdited( false ); + return true; +} + +void TextEdit::clear() +{ + delete doc; + doc = 0; + editor->clear(); +} + +void TextEdit::updateCaption( const QString &name ) +{ + if ( !doc ) + setCaption( tr("Text Editor") ); + else { + QString s = name; + if ( s.isNull() ) + s = doc->name(); + if ( s.isEmpty() ) + s = tr( "Unnamed" ); + setCaption( s + " - " + tr("Text Editor") ); + } +} + +void TextEdit::setDocument(const QString& fileref) +{ + bFromDocView = TRUE; + openFile(DocLnk(fileref)); + showEditTools(); +} + +void TextEdit::closeEvent( QCloseEvent *e ) +{ + if ( editorStack->visibleWidget() == editor && !bFromDocView ) { + e->ignore(); + fileRevert(); + } else { + bFromDocView = FALSE; + e->accept(); + } +} + +void TextEdit::accept() +{ + fileOpen(); +} diff --git a/core/apps/textedit/textedit.h b/core/apps/textedit/textedit.h new file mode 100644 index 0000000..f7d1052 --- a/dev/null +++ b/core/apps/textedit/textedit.h @@ -0,0 +1,102 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef TEXTEDIT_H +#define TEXTEDIT_H + +#define QTEXTEDIT_OPEN_API + +#include + +#include +#include +#include +#include + +class QWidgetStack; +class QToolButton; +class QPopupMenu; +class QToolBar; +class QLineEdit; +class QAction; +class FileSelector; +class QpeEditor; + +class TextEdit : public QMainWindow +{ + Q_OBJECT + +public: + TextEdit( QWidget *parent = 0, const char *name = 0, WFlags f = 0 ); + ~TextEdit(); + + void openFile( const QString & ); + +protected: + void closeEvent( QCloseEvent *e ); + +private slots: + void setDocument(const QString&); + + void fileNew(); + void fileRevert(); + void fileOpen(); + + void editCut(); + void editCopy(); + void editPaste(); + void editFind(); + + void findNext(); + void findClose(); + + void search(); + void accept(); + + void newFile( const DocLnk & ); + void openFile( const DocLnk & ); + void showEditTools(); + + void zoomIn(); + void zoomOut(); + void setBold(bool y); + void setItalic(bool y); + void setWordWrap(bool y); + +private: + void colorChanged( const QColor &c ); + bool save(); + void clear(); + void updateCaption( const QString &name=QString::null ); + void setFontSize(int sz, bool round_down_not_up); + +private: + QWidgetStack *editorStack; + FileSelector *fileSelector; + QpeEditor* editor; + QToolBar *menu, *editBar, *searchBar; + QLineEdit *searchEdit; + DocLnk *doc; + bool searchVisible; + bool bFromDocView; + QAction *zin, *zout; +}; + +#endif diff --git a/core/apps/textedit/textedit.po b/core/apps/textedit/textedit.po new file mode 100644 index 0000000..683a5e3 --- a/dev/null +++ b/core/apps/textedit/textedit.po @@ -0,0 +1,108 @@ +# This is a Qt message file in .po format. Each msgid starts with +# a scope. This scope should *NOT* be translated - eg. translating +# from French to English, "Foo::Bar" would be translated to "Pub", +# not "Foo::Pub". +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2001-03-16 14:29:14 EST\n" +"PO-Revision-Date: YYYY-MM-DD\n" +"Last-Translator: FULLNAME \n" +"Content-Type: text/plain; charset=iso-8859-1\n" + +#: textedit.cpp:110 +msgid "TextEdit::&Edit" +msgstr "" + +#: textedit.cpp:109 +msgid "TextEdit::&File" +msgstr "" + +#: textedit.cpp:102 +msgid "TextEdit::&Insert" +msgstr "" + +#: textedit.cpp:115 +msgid "TextEdit::Bold" +msgstr "" + +#: textedit.cpp:191 +msgid "TextEdit::Bullet List" +msgstr "" + +#: textedit.cpp:140 +msgid "TextEdit::Center" +msgstr "" + +#: textedit.cpp:170 +msgid "TextEdit::Close Find" +msgstr "" + +#: textedit.cpp:69 +msgid "TextEdit::Close" +msgstr "" + +#: textedit.cpp:79 +msgid "TextEdit::Copy" +msgstr "" + +#: textedit.cpp:74 +msgid "TextEdit::Cut" +msgstr "" + +#: textedit.cpp:194 +msgid "TextEdit::Enumerated List" +msgstr "" + +#: textedit.cpp:94 +msgid "TextEdit::Find Next" +msgstr "" + +#: textedit.cpp:89 +msgid "TextEdit::Find..." +msgstr "" + +#: textedit.cpp:120 +msgid "TextEdit::Italic" +msgstr "" + +#: textedit.cpp:134 +msgid "TextEdit::Left" +msgstr "" + +#: textedit.cpp:61 +msgid "TextEdit::New" +msgstr "" + +#: textedit.cpp:65 +msgid "TextEdit::Open" +msgstr "" + +#: textedit.cpp:84 +msgid "TextEdit::Paste" +msgstr "" + +#: textedit.cpp:145 +msgid "TextEdit::Right" +msgstr "" + +#: textedit.cpp:188 +msgid "TextEdit::Standard" +msgstr "" + +#: textedit.cpp:104 +msgid "TextEdit::Table..." +msgstr "" + +#: textedit.cpp:570 +msgid "TextEdit::Text Editor" +msgstr "" + +#: textedit.cpp:125 +msgid "TextEdit::Underline" +msgstr "" + +#: textedit.cpp:569 +msgid "TextEdit::Unnamed" +msgstr "" + diff --git a/core/apps/textedit/textedit.pro b/core/apps/textedit/textedit.pro new file mode 100644 index 0000000..3f5473e --- a/dev/null +++ b/core/apps/textedit/textedit.pro @@ -0,0 +1,16 @@ +TEMPLATE = app +CONFIG += qt warn_on release + +DESTDIR = $(QPEDIR)/bin + +HEADERS = textedit.h + +SOURCES = main.cpp textedit.cpp + +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe + +TARGET = textedit + +TRANSLATIONS = ../i18n/de/textedit.ts diff --git a/core/launcher/.cvsignore b/core/launcher/.cvsignore new file mode 100644 index 0000000..1924a2d --- a/dev/null +++ b/core/launcher/.cvsignore @@ -0,0 +1,7 @@ +moc_* +*.moc +Makefile +shutdown.cpp +shutdown.h +qimpenprefbase.h +lnkpropertiesbase.h diff --git a/core/launcher/Makefile.in b/core/launcher/Makefile.in new file mode 100644 index 0000000..e129fca --- a/dev/null +++ b/core/launcher/Makefile.in @@ -0,0 +1,867 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include -I$(QPEDIR)/calibrate -I$(QPEDIR)/rsync +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe -lcrypt $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = $(QPEDIR)/bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = qpe +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = background.h \ + desktop.h \ + info.h \ + appicons.h \ + taskbar.h \ + sidething.h \ + mrulist.h \ + stabmon.h \ + inputmethods.h \ + systray.h \ + wait.h \ + shutdownimpl.h \ + launcher.h \ + launcherview.h \ + ../calibrate/calibrate.h \ + startmenu.h \ + transferserver.h \ + qcopbridge.h \ + packageslave.h \ + irserver.h \ + $(QPEDIR)/rsync/buf.h \ + $(QPEDIR)/rsync/checksum.h \ + $(QPEDIR)/rsync/command.h \ + $(QPEDIR)/rsync/emit.h \ + $(QPEDIR)/rsync/job.h \ + $(QPEDIR)/rsync/netint.h \ + $(QPEDIR)/rsync/protocol.h \ + $(QPEDIR)/rsync/prototab.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/search.h \ + $(QPEDIR)/rsync/stream.h \ + $(QPEDIR)/rsync/sumset.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/types.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/whole.h \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/qrsync.h +SOURCES = background.cpp \ + desktop.cpp \ + info.cpp \ + appicons.cpp \ + taskbar.cpp \ + sidething.cpp \ + mrulist.cpp \ + stabmon.cpp \ + inputmethods.cpp \ + systray.cpp \ + wait.cpp \ + shutdownimpl.cpp \ + launcher.cpp \ + launcherview.cpp \ + $(QPEDIR)/calibrate/calibrate.cpp \ + transferserver.cpp \ + packageslave.cpp \ + irserver.cpp \ + qcopbridge.cpp \ + startmenu.cpp \ + main.cpp \ + $(QPEDIR)/rsync/base64.c \ + $(QPEDIR)/rsync/buf.c \ + $(QPEDIR)/rsync/checksum.c \ + $(QPEDIR)/rsync/command.c \ + $(QPEDIR)/rsync/delta.c \ + $(QPEDIR)/rsync/emit.c \ + $(QPEDIR)/rsync/hex.c \ + $(QPEDIR)/rsync/job.c \ + $(QPEDIR)/rsync/mdfour.c \ + $(QPEDIR)/rsync/mksum.c \ + $(QPEDIR)/rsync/msg.c \ + $(QPEDIR)/rsync/netint.c \ + $(QPEDIR)/rsync/patch.c \ + $(QPEDIR)/rsync/prototab.c \ + $(QPEDIR)/rsync/readsums.c \ + $(QPEDIR)/rsync/scoop.c \ + $(QPEDIR)/rsync/search.c \ + $(QPEDIR)/rsync/stats.c \ + $(QPEDIR)/rsync/stream.c \ + $(QPEDIR)/rsync/sumset.c \ + $(QPEDIR)/rsync/trace.c \ + $(QPEDIR)/rsync/tube.c \ + $(QPEDIR)/rsync/util.c \ + $(QPEDIR)/rsync/version.c \ + $(QPEDIR)/rsync/whole.c \ + $(QPEDIR)/rsync/qrsync.cpp +OBJECTS = background.o \ + desktop.o \ + info.o \ + appicons.o \ + taskbar.o \ + sidething.o \ + mrulist.o \ + stabmon.o \ + inputmethods.o \ + systray.o \ + wait.o \ + shutdownimpl.o \ + launcher.o \ + launcherview.o \ + $(QPEDIR)/calibrate/calibrate.o \ + transferserver.o \ + packageslave.o \ + irserver.o \ + qcopbridge.o \ + startmenu.o \ + main.o \ + $(QPEDIR)/rsync/base64.o \ + $(QPEDIR)/rsync/buf.o \ + $(QPEDIR)/rsync/checksum.o \ + $(QPEDIR)/rsync/command.o \ + $(QPEDIR)/rsync/delta.o \ + $(QPEDIR)/rsync/emit.o \ + $(QPEDIR)/rsync/hex.o \ + $(QPEDIR)/rsync/job.o \ + $(QPEDIR)/rsync/mdfour.o \ + $(QPEDIR)/rsync/mksum.o \ + $(QPEDIR)/rsync/msg.o \ + $(QPEDIR)/rsync/netint.o \ + $(QPEDIR)/rsync/patch.o \ + $(QPEDIR)/rsync/prototab.o \ + $(QPEDIR)/rsync/readsums.o \ + $(QPEDIR)/rsync/scoop.o \ + $(QPEDIR)/rsync/search.o \ + $(QPEDIR)/rsync/stats.o \ + $(QPEDIR)/rsync/stream.o \ + $(QPEDIR)/rsync/sumset.o \ + $(QPEDIR)/rsync/trace.o \ + $(QPEDIR)/rsync/tube.o \ + $(QPEDIR)/rsync/util.o \ + $(QPEDIR)/rsync/version.o \ + $(QPEDIR)/rsync/whole.o \ + $(QPEDIR)/rsync/qrsync.o \ + shutdown.o \ + syncdialog.o +INTERFACES = shutdown.ui \ + syncdialog.ui +UICDECLS = shutdown.h \ + syncdialog.h +UICIMPLS = shutdown.cpp \ + syncdialog.cpp +SRCMOC = moc_background.cpp \ + moc_desktop.cpp \ + moc_info.cpp \ + moc_appicons.cpp \ + moc_taskbar.cpp \ + moc_sidething.cpp \ + moc_inputmethods.cpp \ + moc_systray.cpp \ + moc_shutdownimpl.cpp \ + moc_launcher.cpp \ + moc_launcherview.cpp \ + ../calibrate/moc_calibrate.cpp \ + moc_startmenu.cpp \ + moc_transferserver.cpp \ + moc_qcopbridge.cpp \ + moc_packageslave.cpp \ + moc_irserver.cpp \ + appicons.moc \ + moc_shutdown.cpp \ + moc_syncdialog.cpp +OBJMOC = moc_background.o \ + moc_desktop.o \ + moc_info.o \ + moc_appicons.o \ + moc_taskbar.o \ + moc_sidething.o \ + moc_inputmethods.o \ + moc_systray.o \ + moc_shutdownimpl.o \ + moc_launcher.o \ + moc_launcherview.o \ + ../calibrate/moc_calibrate.o \ + moc_startmenu.o \ + moc_transferserver.o \ + moc_qcopbridge.o \ + moc_packageslave.o \ + moc_irserver.o \ + moc_shutdown.o \ + moc_syncdialog.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake taskbar.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +background.o: background.cpp \ + background.h \ + desktop.h \ + shutdownimpl.h \ + shutdown.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/resource.h + +desktop.o: desktop.cpp \ + desktop.h \ + shutdownimpl.h \ + shutdown.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + info.h \ + background.h \ + launcher.h \ + launcherview.h \ + $(QPEDIR)/include/qpe/storage.h \ + mrulist.h \ + $(QPEDIR)/include/qpe/applnk.h \ + qcopbridge.h \ + startmenu.h \ + taskbar.h \ + $(QPEDIR)/include/qpe/custom.h \ + transferserver.h \ + irserver.h \ + packageslave.h \ + $(QPEDIR)/include/qpe/mimetype.h \ + $(QPEDIR)/include/qpe/password.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/power.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h \ + $(QPEDIR)/include/qpe/global.h + +info.o: info.cpp \ + info.h \ + background.h \ + desktop.h \ + shutdownimpl.h \ + shutdown.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/version.h + +appicons.o: appicons.cpp \ + appicons.moc \ + appicons.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h + +taskbar.o: taskbar.cpp \ + startmenu.h \ + inputmethods.h \ + $(QPEDIR)/include/qpe/inputmethodinterface.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h \ + mrulist.h \ + $(QPEDIR)/include/qpe/applnk.h \ + systray.h \ + $(QPEDIR)/include/qpe/taskbarappletinterface.h \ + $(QPEDIR)/calibrate/calibrate.h \ + wait.h \ + $(QPEDIR)/include/qpe/resource.h \ + appicons.h \ + taskbar.h \ + $(QPEDIR)/include/qpe/custom.h \ + desktop.h \ + shutdownimpl.h \ + shutdown.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h \ + $(QPEDIR)/include/qpe/global.h \ + ../taskbar/apps.h \ + ../addressbook/addressbook.h \ + ../datebook/datebook.h \ + $(QPEDIR)/include/qpe/datebookdb.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + ../helpbrowser/helpbrowser.h \ + ../minesweep/minesweep.h \ + ../textedit/textedit.h \ + $(QPEDIR)/include/qpe/filemanager.h \ + ../todo/mainwindow.h \ + ../citytime/citytime.h \ + ../clock/clock.h \ + ../calculator/calculatorimpl.h \ + ../sysinfo/sysinfo.h \ + ../settings/appearance/settings.h \ + ../settings/systemtime/settime.h \ + $(QPEDIR)/include/qpe/timestring.h \ + ../filebrowser/filebrowser.h \ + ../solitaire/canvascardwindow.h \ + ../snake/interface.h \ + ../parashoot/interface.h \ + $(QPEDIR)/include/qpe/sound.h \ + ../mpegplayer/mediaplayer.h \ + $(QPEDIR)/include/qpe/qlibrary.h \ + ../embeddedkonsole/konsole.h \ + ../wordgame/wordgame.h \ + $(QPEDIR)/include/qpe/qdawg.h + +sidething.o: sidething.cpp \ + sidething.h \ + startmenu.h \ + $(QPEDIR)/include/qpe/resource.h + +mrulist.o: mrulist.cpp \ + mrulist.h \ + $(QPEDIR)/include/qpe/applnk.h \ + $(QPEDIR)/include/qpe/global.h \ + $(QPEDIR)/include/qpe/resource.h + +stabmon.o: stabmon.cpp \ + stabmon.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h + +inputmethods.o: inputmethods.cpp \ + inputmethods.h \ + $(QPEDIR)/include/qpe/inputmethodinterface.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/qlibrary.h + +systray.o: systray.cpp \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/qlibrary.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h \ + $(QPEDIR)/include/qpe/config.h \ + quicklauncher.h \ + systray.h \ + $(QPEDIR)/include/qpe/taskbarappletinterface.h + +wait.o: wait.cpp \ + wait.h \ + $(QPEDIR)/include/qpe/resource.h + +shutdownimpl.o: shutdownimpl.cpp \ + shutdownimpl.h \ + shutdown.h \ + $(QPEDIR)/include/qpe/global.h + +launcher.o: launcher.cpp \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/applnk.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/global.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/mimetype.h \ + $(QPEDIR)/include/qpe/storage.h \ + launcherview.h \ + launcher.h \ + $(QPEDIR)/include/qpe/lnkproperties.h \ + mrulist.h \ + $(QPEDIR)/rsync/qrsync.h + +launcherview.o: launcherview.cpp \ + launcherview.h \ + $(QPEDIR)/include/qpe/storage.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/applnk.h \ + $(QPEDIR)/include/qpe/qpedebug.h \ + $(QPEDIR)/include/qpe/categories.h \ + $(QPEDIR)/include/qpe/categoryselect.h \ + $(QPEDIR)/include/qpe/menubutton.h \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/qpetoolbar.h + +$(QPEDIR)/calibrate/calibrate.o: $(QPEDIR)/calibrate/calibrate.cpp \ + $(QPEDIR)/calibrate/calibrate.h \ + $(QPEDIR)/include/qpe/resource.h + +transferserver.o: transferserver.cpp \ + $(QPEDIR)/include/qpe/qprocess.h \ + $(QPEDIR)/include/qpe/process.h \ + transferserver.h + +packageslave.o: packageslave.cpp \ + packageslave.h \ + $(QPEDIR)/include/qpe/process.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h + +irserver.o: irserver.cpp \ + irserver.h \ + $(QPEDIR)/include/qpe/qlibrary.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + obexinterface.h + +qcopbridge.o: qcopbridge.cpp \ + qcopbridge.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h \ + $(QPEDIR)/include/qpe/qpeapplication.h + +startmenu.o: startmenu.cpp \ + startmenu.h \ + sidething.h \ + mrulist.h \ + $(QPEDIR)/include/qpe/applnk.h \ + info.h \ + background.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/global.h \ + $(QPEDIR)/include/qpe/resource.h + +main.o: main.cpp \ + desktop.h \ + shutdownimpl.h \ + shutdown.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + taskbar.h \ + $(QPEDIR)/include/qpe/custom.h \ + stabmon.h \ + $(QPEDIR)/include/qpe/network.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h \ + $(QPEDIR)/include/qpe/alarmserver.h \ + ../calibrate/calibrate.h \ + ../login/qdmdialogimpl.h \ + $(QPEDIR)/include/qpe/global.h + +$(QPEDIR)/rsync/base64.o: $(QPEDIR)/rsync/base64.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h + +$(QPEDIR)/rsync/buf.o: $(QPEDIR)/rsync/buf.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/buf.h \ + $(QPEDIR)/rsync/util.h + +$(QPEDIR)/rsync/checksum.o: $(QPEDIR)/rsync/checksum.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/checksum.h + +$(QPEDIR)/rsync/command.o: $(QPEDIR)/rsync/command.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/command.h + +$(QPEDIR)/rsync/delta.o: $(QPEDIR)/rsync/delta.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/emit.h \ + $(QPEDIR)/rsync/stream.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/sumset.h \ + $(QPEDIR)/rsync/job.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/checksum.h \ + $(QPEDIR)/rsync/search.h \ + $(QPEDIR)/rsync/types.h + +$(QPEDIR)/rsync/emit.o: $(QPEDIR)/rsync/emit.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/command.h \ + $(QPEDIR)/rsync/protocol.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/emit.h \ + $(QPEDIR)/rsync/prototab.h \ + $(QPEDIR)/rsync/netint.h \ + $(QPEDIR)/rsync/sumset.h \ + $(QPEDIR)/rsync/job.h + +$(QPEDIR)/rsync/hex.o: $(QPEDIR)/rsync/hex.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h + +$(QPEDIR)/rsync/job.o: $(QPEDIR)/rsync/job.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/stream.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/sumset.h \ + $(QPEDIR)/rsync/job.h \ + $(QPEDIR)/rsync/trace.h + +$(QPEDIR)/rsync/mdfour.o: $(QPEDIR)/rsync/mdfour.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/types.h + +$(QPEDIR)/rsync/mksum.o: $(QPEDIR)/rsync/mksum.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/stream.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/sumset.h \ + $(QPEDIR)/rsync/job.h \ + $(QPEDIR)/rsync/protocol.h \ + $(QPEDIR)/rsync/netint.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/checksum.h + +$(QPEDIR)/rsync/msg.o: $(QPEDIR)/rsync/msg.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h + +$(QPEDIR)/rsync/netint.o: $(QPEDIR)/rsync/netint.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/job.h \ + $(QPEDIR)/rsync/netint.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/stream.h + +$(QPEDIR)/rsync/patch.o: $(QPEDIR)/rsync/patch.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/protocol.h \ + $(QPEDIR)/rsync/netint.h \ + $(QPEDIR)/rsync/command.h \ + $(QPEDIR)/rsync/sumset.h \ + $(QPEDIR)/rsync/prototab.h \ + $(QPEDIR)/rsync/stream.h \ + $(QPEDIR)/rsync/job.h + +$(QPEDIR)/rsync/prototab.o: $(QPEDIR)/rsync/prototab.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/protocol.h \ + $(QPEDIR)/rsync/command.h \ + $(QPEDIR)/rsync/prototab.h + +$(QPEDIR)/rsync/readsums.o: $(QPEDIR)/rsync/readsums.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/sumset.h \ + $(QPEDIR)/rsync/job.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/netint.h \ + $(QPEDIR)/rsync/protocol.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/stream.h + +$(QPEDIR)/rsync/scoop.o: $(QPEDIR)/rsync/scoop.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/job.h \ + $(QPEDIR)/rsync/stream.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/util.h + +$(QPEDIR)/rsync/search.o: $(QPEDIR)/rsync/search.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/sumset.h \ + $(QPEDIR)/rsync/search.h \ + $(QPEDIR)/rsync/checksum.h + +$(QPEDIR)/rsync/stats.o: $(QPEDIR)/rsync/stats.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/trace.h + +$(QPEDIR)/rsync/stream.o: $(QPEDIR)/rsync/stream.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/stream.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/trace.h + +$(QPEDIR)/rsync/sumset.o: $(QPEDIR)/rsync/sumset.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/sumset.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/trace.h + +$(QPEDIR)/rsync/trace.o: $(QPEDIR)/rsync/trace.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/trace.h + +$(QPEDIR)/rsync/tube.o: $(QPEDIR)/rsync/tube.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/job.h \ + $(QPEDIR)/rsync/stream.h + +$(QPEDIR)/rsync/util.o: $(QPEDIR)/rsync/util.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/trace.h + +$(QPEDIR)/rsync/version.o: $(QPEDIR)/rsync/version.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h + +$(QPEDIR)/rsync/whole.o: $(QPEDIR)/rsync/whole.c \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/config_linux.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/fileutil.h \ + $(QPEDIR)/rsync/sumset.h \ + $(QPEDIR)/rsync/job.h \ + $(QPEDIR)/rsync/buf.h \ + $(QPEDIR)/rsync/whole.h \ + $(QPEDIR)/rsync/util.h + +$(QPEDIR)/rsync/qrsync.o: $(QPEDIR)/rsync/qrsync.cpp \ + $(QPEDIR)/rsync/qrsync.h \ + $(QPEDIR)/rsync/rsync.h + +shutdown.h: shutdown.ui + $(UIC) shutdown.ui -o $(INTERFACE_DECL_PATH)/shutdown.h + +shutdown.cpp: shutdown.ui + $(UIC) shutdown.ui -i shutdown.h -o shutdown.cpp + +syncdialog.h: syncdialog.ui + $(UIC) syncdialog.ui -o $(INTERFACE_DECL_PATH)/syncdialog.h + +syncdialog.cpp: syncdialog.ui + $(UIC) syncdialog.ui -i syncdialog.h -o syncdialog.cpp + +shutdown.o: shutdown.cpp \ + shutdown.h + +syncdialog.o: syncdialog.cpp + +moc_background.o: moc_background.cpp \ + background.h + +moc_desktop.o: moc_desktop.cpp \ + desktop.h \ + shutdownimpl.h \ + shutdown.h \ + $(QPEDIR)/include/qpe/qpeapplication.h + +moc_info.o: moc_info.cpp \ + info.h \ + background.h + +moc_appicons.o: moc_appicons.cpp \ + appicons.h + +moc_taskbar.o: moc_taskbar.cpp \ + taskbar.h \ + $(QPEDIR)/include/qpe/custom.h + +moc_sidething.o: moc_sidething.cpp \ + sidething.h \ + startmenu.h + +moc_inputmethods.o: moc_inputmethods.cpp \ + inputmethods.h \ + $(QPEDIR)/include/qpe/inputmethodinterface.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h + +moc_systray.o: moc_systray.cpp \ + systray.h \ + $(QPEDIR)/include/qpe/taskbarappletinterface.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h + +moc_shutdownimpl.o: moc_shutdownimpl.cpp \ + shutdownimpl.h \ + shutdown.h + +moc_launcher.o: moc_launcher.cpp \ + launcher.h \ + launcherview.h \ + $(QPEDIR)/include/qpe/storage.h + +moc_launcherview.o: moc_launcherview.cpp \ + launcherview.h \ + $(QPEDIR)/include/qpe/storage.h + +../calibrate/moc_calibrate.o: ../calibrate/moc_calibrate.cpp \ + ../calibrate/calibrate.h + +moc_startmenu.o: moc_startmenu.cpp \ + startmenu.h + +moc_transferserver.o: moc_transferserver.cpp \ + transferserver.h + +moc_qcopbridge.o: moc_qcopbridge.cpp \ + qcopbridge.h + +moc_packageslave.o: moc_packageslave.cpp \ + packageslave.h + +moc_irserver.o: moc_irserver.cpp \ + irserver.h + +moc_shutdown.o: appicons.moc \ + appicons.cpp \ + appicons.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h + +moc_syncdialog.o: moc_shutdown.cpp \ + shutdown.h + +moc_background.cpp: background.h + $(MOC) background.h -o moc_background.cpp + +moc_desktop.cpp: desktop.h + $(MOC) desktop.h -o moc_desktop.cpp + +moc_info.cpp: info.h + $(MOC) info.h -o moc_info.cpp + +moc_appicons.cpp: appicons.h + $(MOC) appicons.h -o moc_appicons.cpp + +moc_taskbar.cpp: taskbar.h + $(MOC) taskbar.h -o moc_taskbar.cpp + +moc_sidething.cpp: sidething.h + $(MOC) sidething.h -o moc_sidething.cpp + +moc_inputmethods.cpp: inputmethods.h + $(MOC) inputmethods.h -o moc_inputmethods.cpp + +moc_systray.cpp: systray.h + $(MOC) systray.h -o moc_systray.cpp + +moc_shutdownimpl.cpp: shutdownimpl.h + $(MOC) shutdownimpl.h -o moc_shutdownimpl.cpp + +moc_launcher.cpp: launcher.h + $(MOC) launcher.h -o moc_launcher.cpp + +moc_launcherview.cpp: launcherview.h + $(MOC) launcherview.h -o moc_launcherview.cpp + +../calibrate/moc_calibrate.cpp: ../calibrate/calibrate.h + $(MOC) ../calibrate/calibrate.h -o ../calibrate/moc_calibrate.cpp + +moc_startmenu.cpp: startmenu.h + $(MOC) startmenu.h -o moc_startmenu.cpp + +moc_transferserver.cpp: transferserver.h + $(MOC) transferserver.h -o moc_transferserver.cpp + +moc_qcopbridge.cpp: qcopbridge.h + $(MOC) qcopbridge.h -o moc_qcopbridge.cpp + +moc_packageslave.cpp: packageslave.h + $(MOC) packageslave.h -o moc_packageslave.cpp + +moc_irserver.cpp: irserver.h + $(MOC) irserver.h -o moc_irserver.cpp + +appicons.moc: appicons.cpp + $(MOC) appicons.cpp -o appicons.moc + +moc_shutdown.cpp: shutdown.h + $(MOC) shutdown.h -o moc_shutdown.cpp + +moc_syncdialog.cpp: syncdialog.h + $(MOC) syncdialog.h -o moc_syncdialog.cpp + + diff --git a/core/launcher/appicons.cpp b/core/launcher/appicons.cpp new file mode 100644 index 0000000..c51ee5a --- a/dev/null +++ b/core/launcher/appicons.cpp @@ -0,0 +1,129 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + + +#include "appicons.h" + +#include + +#include +#include + + +AppIcons::AppIcons( QWidget *parent ) : + QHBox(parent) +{ + buttons.setAutoDelete(TRUE); + +#ifndef QT_NO_COP + QCopChannel* channel = new QCopChannel("Qt/Tray", this); + connect(channel, SIGNAL(received(const QCString&, const QByteArray&)), + this, SLOT(receive(const QCString&, const QByteArray&))); +#endif +} + +void AppIcons::setIcon(int id, const QPixmap& pm) +{ + button(id)->setPixmap(pm); +} + +class FlatButton : public QLabel { + Q_OBJECT +public: + FlatButton(QWidget* parent) : QLabel(parent) { } + + void mouseDoubleClickEvent(QMouseEvent* e) + { + emit clicked(e->pos(),e->button(),TRUE); + } + void mouseReleaseEvent(QMouseEvent* e) + { + if ( rect().contains(e->pos()) ) + emit clicked(e->pos(),e->button(),FALSE); + } + +signals: + void clicked(const QPoint&, int, bool); +}; + +QLabel* AppIcons::button(int id) +{ + QLabel* f = buttons.find(id); + if ( !f ) { + buttons.insert(id,f=new FlatButton(this)); + connect(f,SIGNAL(clicked(const QPoint&, int, bool)),this,SLOT(clicked(const QPoint&, int, bool))); + f->show(); + } + return f; +} + +int AppIcons::findId(QLabel* b) +{ + QIntDictIterator it(buttons); + for ( ; ; ++it ) + if ( it.current() == b ) return it.currentKey(); +} + +void AppIcons::clicked(const QPoint& relpos, int button, bool dbl) +{ +#ifndef QT_NO_COP + QLabel* s = (QLabel*)sender(); + if ( button == RightButton ) { + QCopEnvelope("Qt/Tray","popup(int,QPoint)") + << findId(s) << s->mapToGlobal(QPoint(0,0)); + } else { + QCopEnvelope("Qt/Tray", + dbl ? "doubleClicked(int,QPoint)" : "clicked(int,QPoint)") + << findId(s) << relpos; + } +#endif +} + +void AppIcons::setToolTip(int id, const QString& tip) +{ + QToolTip::add(button(id),tip); +} + +void AppIcons::remove(int id) +{ + buttons.remove(id); +} + +void AppIcons::receive( const QCString &msg, const QByteArray &data ) +{ + QDataStream stream( data, IO_ReadOnly ); + if ( msg == "remove(int)" ) { + int id; + stream >> id; + remove(id); + } else if ( msg == "setIcon(int,QPixmap)" ) { + int id; + QPixmap pm; + stream >> id >> pm; + setIcon(id,pm); + } else if ( msg == "setToolTip(int,QString)" ) { + int id; + QString s; + stream >> id >> s; + setToolTip(id,s); + } +} + +#include "appicons.moc" diff --git a/core/launcher/appicons.h b/core/launcher/appicons.h new file mode 100644 index 0000000..f53f4a7 --- a/dev/null +++ b/core/launcher/appicons.h @@ -0,0 +1,51 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef APPICONS_H +#define APPICONS_H + + +#include +#include +#include + + +class AppIcons : public QHBox +{ + Q_OBJECT + +public: + AppIcons( QWidget *parent ); + void setIcon(int id, const QPixmap&); + void setToolTip(int id, const QString&); + void remove(int id); + +private slots: + void receive( const QCString &msg, const QByteArray &data ); + void clicked(const QPoint& relpos, int button, bool dbl); + +private: + QIntDict buttons; + QLabel* button(int id); + int findId(QLabel*); +}; + + +#endif diff --git a/core/launcher/apps.h b/core/launcher/apps.h new file mode 100644 index 0000000..6216941 --- a/dev/null +++ b/core/launcher/apps.h @@ -0,0 +1,83 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + + +// To add a new app, include appropriate files and add another APP(). + +#ifndef APP_INCLUDES +#define APP_INCLUDES + +#include "../addressbook/addressbook.h" +#include "../datebook/datebook.h" +#include "../helpbrowser/helpbrowser.h" +#include "../minesweep/minesweep.h" +#include "../textedit/textedit.h" +#include "../todo/mainwindow.h" +#include "../citytime/citytime.h" +#include "../clock/clock.h" +#include "../calculator/calculatorimpl.h" +#include "../sysinfo/sysinfo.h" +#include "../settings/appearance/settings.h" +//#include "../settings/language/settings.h" +//#include "../settings/light-and-power/settings.h" +//#include "../settings/rotation/settings.h" +#include "../settings/systemtime/settime.h" +#if !defined(QT_QPE_SMALL_BUILD) +#include "../filebrowser/filebrowser.h" +#include "../solitaire/canvascardwindow.h" +#include "../snake/interface.h" +#include "../parashoot/interface.h" +#include "../mpegplayer/mediaplayer.h" +#endif +#if !defined(QT_DEMO_SINGLE_FLOPPY) && !defined(QT_QPE_SMALL_BUILD) +#include "../embeddedkonsole/konsole.h" +#include "../wordgame/wordgame.h" +#endif + +#endif + +// app-id class maximize? documentary? + +APP( "addressbook", AddressbookWindow, 1, 0 ) +APP( "datebook", DateBook, 1, 0 ) +APP( "helpbrowser", HelpBrowser, 1, 1 ) +APP( "textedit", TextEdit, 1, 1 ) +APP( "todo", TodoWindow, 1, 0 ) +APP( "calculator", CalculatorImpl, 1, 0 ) +APP( "citytime", CityTime, 1, 0 ) +APP( "clock", Clock, 1, 0 ) +APP( "minesweep", MineSweep, 1, 0 ) +APP( "sysinfo", SystemInfo, 1, 0 ) +APP( "appearance", AppearanceSettings, 1, 0 ) +APP( "systemtime", SetDateTime, 1, 0 ) +#if !defined(QT_QPE_SMALL_BUILD) +//APP( "light-and-power", LightSettings, 1, 0 ) +//APP( "sound", SoundSettings, 1, 0 ) +APP( "filebrowser", FileBrowser, 1, 0 ) +APP( "solitaire", CanvasCardWindow, 1, 0 ) +APP( "snake", SnakeGame, 1, 0 ) +APP( "parashoot", ParaShoot, 1, 0 ) +APP( "mpegplayer", MediaPlayer, 1, 0 ) +#endif +#if !defined(QT_DEMO_SINGLE_FLOPPY) && !defined(QT_QPE_SMALL_BUILD) +APP( "embeddedkonsole", Konsole, 1, 0 ) +APP( "wordgame", WordGame, 1, 0 ) +#endif + diff --git a/core/launcher/background.cpp b/core/launcher/background.cpp new file mode 100644 index 0000000..04ebc37 --- a/dev/null +++ b/core/launcher/background.cpp @@ -0,0 +1,41 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "background.h" +#include "desktop.h" + +#include + +#include + + +Background::Background( Desktop *d ) : + QWidget( d, 0, WStyle_Tool | WStyle_Customize ) +{ +/* + if ( QPixmap::defaultDepth() < 12 ) { + setBackgroundColor(QColor(0x20, 0xb0, 0x50)); + } else { + setBackgroundPixmap( Resource::loadPixmap( "bg" ) ); + } +*/ + setBackgroundMode( PaletteButton ); +} + diff --git a/core/launcher/background.h b/core/launcher/background.h new file mode 100644 index 0000000..0885747 --- a/dev/null +++ b/core/launcher/background.h @@ -0,0 +1,40 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __BACKGROUND_H__ +#define __BACKGROUND_H__ + + +#include + + +class Desktop; + + +class Background : public QWidget { + Q_OBJECT +public: + Background( Desktop *d ); +}; + + +#endif // __BACKGROUND_H__ + + diff --git a/core/launcher/desktop.cpp b/core/launcher/desktop.cpp new file mode 100644 index 0000000..d39af25 --- a/dev/null +++ b/core/launcher/desktop.cpp @@ -0,0 +1,655 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "desktop.h" +#include "info.h" +#include "launcher.h" +#include "mrulist.h" +#include "qcopbridge.h" +#include "shutdownimpl.h" +#include "startmenu.h" +#include "taskbar.h" +#include "transferserver.h" +#include "irserver.h" +#include "packageslave.h" + +#include +#include +#include +#include +#include +#include +#include +#ifdef QT_QWS_CUSTOM +#include "qpe/custom.h" +#endif + +#include +#include +#include +#include +#include + +#include +#include + +static Desktop* qpedesktop = 0; +static int loggedin=0; +static void login(bool at_poweron) +{ + if ( !loggedin ) { + Global::terminateBuiltin("calibrate"); + Password::authenticate(at_poweron); + loggedin=1; + QCopEnvelope e( "QPE/Desktop", "unlocked()" ); + } +} + +bool Desktop::screenLocked() +{ + return loggedin == 0; +} + +/* + Priority is number of alerts that are needed to pop up + alert. + */ +class DesktopPowerAlerter : public QMessageBox +{ +public: + DesktopPowerAlerter( QWidget *parent, const char *name = 0 ) + : QMessageBox( tr("Battery Status"), "Low Battery", + QMessageBox::Critical, + QMessageBox::Ok | QMessageBox::Default, + QMessageBox::NoButton, QMessageBox::NoButton, + parent, name, FALSE ) + { + currentPriority = INT_MAX; + alertCount = 0; + } + + void alert( const QString &text, int priority ); + void hideEvent( QHideEvent * ); +private: + int currentPriority; + int alertCount; +}; + +void DesktopPowerAlerter::alert( const QString &text, int priority ) +{ + alertCount++; + if ( alertCount < priority ) + return; + if ( priority > currentPriority ) + return; + currentPriority = priority; + setText( text ); + show(); +} + + +void DesktopPowerAlerter::hideEvent( QHideEvent *e ) +{ + QMessageBox::hideEvent( e ); + alertCount = 0; + currentPriority = INT_MAX; +} + + + +DesktopApplication::DesktopApplication( int& argc, char **argv, Type t ) + : QPEApplication( argc, argv, t ) +{ + + QTimer *t = new QTimer( this ); + connect( t, SIGNAL(timeout()), this, SLOT(psTimeout()) ); + t->start( 10000 ); + ps = new PowerStatus; + pa = new DesktopPowerAlerter( 0 ); +} + + +DesktopApplication::~DesktopApplication() +{ + delete ps; + delete pa; +} + + +enum MemState { Unknown, VeryLow, Low, Normal } memstate=Unknown; + +#ifdef Q_WS_QWS +bool DesktopApplication::qwsEventFilter( QWSEvent *e ) +{ + qpedesktop->checkMemory(); + + if ( e->type == QWSEvent::Key ) { + QWSKeyEvent *ke = (QWSKeyEvent *)e; + if ( !loggedin && ke->simpleData.keycode != Key_F34 ) + return TRUE; + bool press = ke->simpleData.is_press; + if ( !keyboardGrabbed() ) { + if ( ke->simpleData.keycode == Key_F9 ) { + if ( press ) emit datebook(); + return TRUE; + } + if ( ke->simpleData.keycode == Key_F10 ) { + if ( !press && cardSendTimer ) { + emit contacts(); + delete cardSendTimer; + } else if ( press ) { + cardSendTimer = new QTimer(); + cardSendTimer->start( 2000, TRUE ); + connect( cardSendTimer, SIGNAL( timeout() ), this, SLOT( sendCard() ) ); + } + return TRUE; + } + /* menu key now opens application menu/toolbar + if ( ke->simpleData.keycode == Key_F11 ) { + if ( press ) emit menu(); + return TRUE; + } + */ + if ( ke->simpleData.keycode == Key_F12 ) { + while( activePopupWidget() ) + activePopupWidget()->close(); + if ( press ) emit launch(); + return TRUE; + } + if ( ke->simpleData.keycode == Key_F13 ) { + if ( press ) emit email(); + return TRUE; + } + } + if ( ke->simpleData.keycode == Key_F34 ) { + if ( press ) emit power(); + return TRUE; + } + if ( ke->simpleData.keycode == Key_F35 ) { + if ( press ) emit backlight(); + return TRUE; + } + if ( ke->simpleData.keycode == Key_F32 ) { + if ( press ) QCopEnvelope e( "QPE/Desktop", "startSync()" ); + return TRUE; + } + if ( ke->simpleData.keycode == Key_F31 && !ke->simpleData.modifiers ) { + if ( press ) emit symbol(); + return TRUE; + } + if ( ke->simpleData.keycode == Key_NumLock ) { + if ( press ) emit numLockStateToggle(); + } + if ( ke->simpleData.keycode == Key_CapsLock ) { + if ( press ) emit capsLockStateToggle(); + } + if ( press ) + qpedesktop->keyClick(); + } else { + if ( e->type == QWSEvent::Mouse ) { + QWSMouseEvent *me = (QWSMouseEvent *)e; + static bool up = TRUE; + if ( me->simpleData.state&LeftButton ) { + if ( up ) { + up = FALSE; + qpedesktop->screenClick(); + } + } else { + up = TRUE; + } + } + } + + return QPEApplication::qwsEventFilter( e ); +} +#endif + +void DesktopApplication::psTimeout() +{ + qpedesktop->checkMemory(); // in case no events are being generated + + *ps = PowerStatusManager::readStatus(); + + if ( (ps->batteryStatus() == PowerStatus::VeryLow ) ) { + pa->alert( tr( "Battery is running very low." ), 6 ); + } + + if ( ps->batteryStatus() == PowerStatus::Critical ) { + pa->alert( tr( "Battery level is critical!\n" + "Keep power off until power restored!" ), 1 ); + } + + if ( ps->backupBatteryStatus() == PowerStatus::VeryLow ) { + pa->alert( tr( "The Back-up battery is very low.\nPlease charge the back-up battery." ), 3 ); + } +} + + +void DesktopApplication::sendCard() +{ + delete cardSendTimer; + cardSendTimer = 0; + QString card = getenv("HOME"); + card += "/Applications/addressbook/businesscard.vcf"; + + if ( QFile::exists( card ) ) { + QCopEnvelope e("QPE/Obex", "send(QString,QString,QString)"); + QString mimetype = "text/x-vCard"; + e << tr("business card") << card << mimetype; + } +} + +#if defined(QPE_HAVE_MEMALERTER) +QPE_MEMALERTER_IMPL +#endif + +#if defined(CUSTOM_SOUND_IMPL) +CUSTOM_SOUND_IMPL +#endif + +//=========================================================================== + +Desktop::Desktop() : + QWidget( 0, 0, WStyle_Tool | WStyle_Customize ), + qcopBridge( 0 ), + transferServer( 0 ), + packageSlave( 0 ) +{ +#ifdef CUSTOM_SOUND_INIT + CUSTOM_SOUND_INIT; +#endif + + qpedesktop = this; + +// bg = new Info( this ); + tb = new TaskBar; + + launcher = new Launcher( 0, 0, WStyle_Customize | QWidget::WGroupLeader ); + + connect(launcher, SIGNAL(busy()), tb, SLOT(startWait())); + connect(launcher, SIGNAL(notBusy(const QString&)), tb, SLOT(stopWait(const QString&))); + + int displayw = qApp->desktop()->width(); + int displayh = qApp->desktop()->height(); + + + QSize sz = tb->sizeHint(); + + setGeometry( 0, displayh-sz.height(), displayw, sz.height() ); + tb->setGeometry( 0, displayh-sz.height(), displayw, sz.height() ); + + tb->show(); + launcher->showMaximized(); + launcher->show(); + launcher->raise(); +#if defined(QPE_HAVE_MEMALERTER) + initMemalerter(); +#endif + // start services + startTransferServer(); + (void) new IrServer( this ); + rereadVolumes(); + + packageSlave = new PackageSlave( this ); + connect(qApp, SIGNAL(volumeChanged(bool)), this, SLOT(rereadVolumes())); + + qApp->installEventFilter( this ); +} + +void Desktop::show() +{ + login(TRUE); + QWidget::show(); +} + +Desktop::~Desktop() +{ + delete launcher; + delete tb; + delete qcopBridge; + delete transferServer; +} + +bool Desktop::recoverMemory() +{ + return tb->recoverMemory(); +} + +void Desktop::checkMemory() +{ +#if defined(QPE_HAVE_MEMALERTER) + static bool ignoreNormal=FALSE; + static bool existingMessage=FALSE; + + if(existingMessage) + return; // don't show a second message while still on first + + existingMessage = TRUE; + switch ( memstate ) { + case Unknown: + break; + case Low: + memstate = Unknown; + if ( recoverMemory() ) + ignoreNormal = TRUE; + else + QMessageBox::warning( 0 , "Memory Status", + "The memory smacks of shortage. \n" + "Please save data. " ); + break; + case Normal: + memstate = Unknown; + if ( ignoreNormal ) + ignoreNormal = FALSE; + else + QMessageBox::information ( 0 , "Memory Status", + "There is enough memory again." ); + break; + case VeryLow: + memstate = Unknown; + QMessageBox::critical( 0 , "Memory Status", + "The memory is very low. \n" + "Please end this application \n" + "immediately." ); + recoverMemory(); + } + existingMessage = FALSE; +#endif +} + +static bool isVisibleWindow(int wid) +{ + const QList &list = qwsServer->clientWindows(); + QWSWindow* w; + for (QListIterator it(list); (w=it.current()); ++it) { + if ( w->winId() == wid ) + return !w->isFullyObscured(); + } + return FALSE; +} + +static bool hasVisibleWindow(const QString& clientname) +{ + const QList &list = qwsServer->clientWindows(); + QWSWindow* w; + for (QListIterator it(list); (w=it.current()); ++it) { + if ( w->client()->identity() == clientname && !w->isFullyObscured() ) + return TRUE; + } + return FALSE; +} + +void Desktop::raiseLauncher() +{ + if ( isVisibleWindow(launcher->winId()) ) + launcher->nextView(); + else + launcher->raise(); +} + +void Desktop::executeOrModify(const QString& appLnkFile) +{ + AppLnk lnk(MimeType::appsFolderName() + "/" + appLnkFile); + if ( lnk.isValid() ) { + QCString app = lnk.exec().utf8(); + Global::terminateBuiltin("calibrate"); + if ( QCopChannel::isRegistered("QPE/Application/" + app) ) { + MRUList::addTask(&lnk); + if ( hasVisibleWindow(app) ) + QCopChannel::send("QPE/Application/" + app, "nextView()"); + else + QCopChannel::send("QPE/Application/" + app, "raise()"); + } else { + lnk.execute(); + } + } +} + +void Desktop::raiseDatebook() +{ + executeOrModify("Applications/datebook.desktop"); +} + +void Desktop::raiseContacts() +{ + executeOrModify("Applications/addressbook.desktop"); +} + +void Desktop::raiseMenu() +{ + Global::terminateBuiltin("calibrate"); + tb->startMenu()->launch(); +} + +void Desktop::raiseEmail() +{ + executeOrModify("Applications/qtmail.desktop"); +} + +#if defined(QPE_HAVE_TOGGLELIGHT) +#include + +#include +#include +#include +#include +#include +#include +#include +#endif + +static bool blanked=FALSE; + +static void blankScreen() +{ + if ( !qt_screen ) return; + /* Should use a big black window instead. + QGfx* g = qt_screen->screenGfx(); + g->fillRect(0,0,qt_screen->width(),qt_screen->height()); + delete g; + */ + blanked = TRUE; +} + +static void darkScreen() +{ + extern void qpe_setBacklight(int); + qpe_setBacklight(0); // force off +} + + +void Desktop::togglePower() +{ + bool wasloggedin = loggedin; + loggedin=0; + darkScreen(); + if ( wasloggedin ) + blankScreen(); + system("apm --suspend"); + QWSServer::screenSaverActivate( FALSE ); + { + QCopEnvelope("QPE/Card", "mtabChanged()" ); // might have changed while asleep + QCopEnvelope e("QPE/System", "setBacklight(int)"); + e << -3; // Force on + } + if ( wasloggedin ) + login(TRUE); + //qcopBridge->closeOpenConnections(); + //qDebug("called togglePower()!!!!!!"); +} + +void Desktop::toggleLight() +{ + QCopEnvelope e("QPE/System", "setBacklight(int)"); + e << -2; // toggle +} + +void Desktop::toggleSymbolInput() +{ + tb->toggleSymbolInput(); +} + +void Desktop::toggleNumLockState() +{ + tb->toggleNumLockState(); +} + +void Desktop::toggleCapsLockState() +{ + tb->toggleCapsLockState(); +} + +void Desktop::styleChange( QStyle &s ) +{ + QWidget::styleChange( s ); + int displayw = qApp->desktop()->width(); + int displayh = qApp->desktop()->height(); + + QSize sz = tb->sizeHint(); + + tb->setGeometry( 0, displayh-sz.height(), displayw, sz.height() ); +} + +void DesktopApplication::shutdown() +{ + if ( type() != GuiServer ) + return; + ShutdownImpl *sd = new ShutdownImpl( 0, 0, WDestructiveClose ); + connect( sd, SIGNAL(shutdown(ShutdownImpl::Type)), + this, SLOT(shutdown(ShutdownImpl::Type)) ); + sd->showMaximized(); +} + +void DesktopApplication::shutdown( ShutdownImpl::Type t ) +{ + switch ( t ) { + case ShutdownImpl::ShutdownSystem: + execlp("shutdown", "shutdown", "-h", "now", (void*)0); + break; + case ShutdownImpl::RebootSystem: + execlp("shutdown", "shutdown", "-r", "now", (void*)0); + break; + case ShutdownImpl::RestartDesktop: + restart(); + break; + case ShutdownImpl::TerminateDesktop: + prepareForTermination(FALSE); + quit(); + break; + } +} + +void DesktopApplication::restart() +{ + prepareForTermination(TRUE); + +#ifdef Q_WS_QWS + for ( int fd = 3; fd < 100; fd++ ) + close( fd ); +#if defined(QT_DEMO_SINGLE_FLOPPY) + execl( "/sbin/init", "qpe", 0 ); +#elif defined(QT_QWS_CASSIOPEIA) + execl( "/bin/sh", "sh", 0 ); +#else + execl( (qpeDir()+"/bin/qpe").latin1(), "qpe", 0 ); +#endif + exit(1); +#endif +} + +void Desktop::startTransferServer() +{ + // start qcop bridge server + qcopBridge = new QCopBridge( 4243 ); + if ( !qcopBridge->ok() ) { + delete qcopBridge; + qcopBridge = 0; + } + // start transfer server + transferServer = new TransferServer( 4242 ); + if ( !transferServer->ok() ) { + delete transferServer; + transferServer = 0; + } + if ( !transferServer || !qcopBridge ) + startTimer( 2000 ); +} + +void Desktop::timerEvent( QTimerEvent *e ) +{ + killTimer( e->timerId() ); + startTransferServer(); +} + +void Desktop::terminateServers() +{ + delete transferServer; + delete qcopBridge; + transferServer = 0; + qcopBridge = 0; +} + +void Desktop::rereadVolumes() +{ + Config cfg("Sound"); + cfg.setGroup("System"); + touchclick = cfg.readBoolEntry("Touch"); + keyclick = cfg.readBoolEntry("Key"); +} + +void Desktop::keyClick() +{ +#ifdef CUSTOM_SOUND_KEYCLICK + if ( keyclick ) + CUSTOM_SOUND_KEYCLICK; +#endif +} + +void Desktop::screenClick() +{ +#ifdef CUSTOM_SOUND_TOUCH + if ( touchclick ) + CUSTOM_SOUND_TOUCH; +#endif +} + +void Desktop::soundAlarm() +{ +#ifdef CUSTOM_SOUND_ALARM + CUSTOM_SOUND_ALARM; +#endif +} + +bool Desktop::eventFilter( QObject *w, QEvent *ev ) +{ + if ( ev->type() == QEvent::KeyPress ) { + QKeyEvent *ke = (QKeyEvent *)ev; + if ( ke->key() == Qt::Key_F11 ) { // menu key + QWidget *active = qApp->activeWindow(); + if ( active && active->isPopup() ) { + active->close(); + } + raiseMenu(); + return TRUE; + } + } + return FALSE; +} + diff --git a/core/launcher/desktop.h b/core/launcher/desktop.h new file mode 100644 index 0000000..dfdbeab --- a/dev/null +++ b/core/launcher/desktop.h @@ -0,0 +1,129 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __DESKTOP_H__ +#define __DESKTOP_H__ + + +#include "shutdownimpl.h" + +#include + +#include + +class Background; +class Launcher; +class TaskBar; +class PowerStatus; +class QCopBridge; +class TransferServer; +class DesktopPowerAlerter; +class PackageSlave; + +class DesktopApplication : public QPEApplication +{ + Q_OBJECT +public: + DesktopApplication( int& argc, char **argv, Type t ); + ~DesktopApplication(); +signals: + void home(); + void datebook(); + void contacts(); + void launch(); + void email(); + void backlight(); + void power(); + void symbol(); + void numLockStateToggle(); + void capsLockStateToggle(); + void prepareForRestart(); + +protected: +#ifdef Q_WS_QWS + bool qwsEventFilter( QWSEvent * ); +#endif + void shutdown(); + void restart(); + +protected slots: + void shutdown(ShutdownImpl::Type); + void psTimeout(); + void sendCard(); +private: + DesktopPowerAlerter *pa; + PowerStatus *ps; + QTimer *cardSendTimer; +}; + + +class Desktop : public QWidget { + Q_OBJECT +public: + Desktop(); + ~Desktop(); + + static bool screenLocked(); + + void show(); + void checkMemory(); + + void keyClick(); + void screenClick(); + static void soundAlarm(); + +public slots: + void raiseDatebook(); + void raiseContacts(); + void raiseMenu(); + void raiseLauncher(); + void raiseEmail(); + void togglePower(); + void toggleLight(); + void toggleNumLockState(); + void toggleCapsLockState(); + void toggleSymbolInput(); + void terminateServers(); + void rereadVolumes(); + +protected: + void executeOrModify(const QString& appLnkFile); + void styleChange( QStyle & ); + void timerEvent( QTimerEvent *e ); + bool eventFilter( QObject *, QEvent * ); + + QWidget *bg; + Launcher *launcher; + TaskBar *tb; + +private: + void startTransferServer(); + bool recoverMemory(); + + QCopBridge *qcopBridge; + TransferServer *transferServer; + PackageSlave *packageSlave; + + bool keyclick,touchclick; +}; + + +#endif // __DESKTOP_H__ + diff --git a/core/launcher/info.cpp b/core/launcher/info.cpp new file mode 100644 index 0000000..609e9e2 --- a/dev/null +++ b/core/launcher/info.cpp @@ -0,0 +1,116 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "info.h" +#include "desktop.h" + +#include +#include + +#include +#include +#include +#include + + +Info *desktopInfo = NULL; + + +Info::Info( Desktop *d ) : Background( d ), needsClear(FALSE), menuHasBeenClicked(FALSE) +{ + QString motd; + /* eg. + = + "" + "" + "

Today    June 15, 2001

Appointments" + "
" + "8:30am Meeting with John
" + "1:10pm Lunch with Sharon" + "
Reminders" + "
" + "#1 Port XMAME to QPE
" + "#2 Flowers for wife" + "
Net channels" + "
" + "LinuxDevices: QPE announcement
" + "Slashdot: GPL Examined" + "
"; + */ + info = new QSimpleRichText(motd, QFont("lucidux_sans",10)); + desktopInfo = this; +} + + +void Info::mouseReleaseEvent( QMouseEvent * ) +{ +} + + +void Info::menuClicked( ) +{ + QPainter p(this); + if ( needsClear ) { + QColor col = colorGroup().color( QColorGroup::Button ).dark( 0 ); + p.fillRect( 5, height() - 24, width() - 5, 20, col ); + needsClear = FALSE; + menuHasBeenClicked = TRUE; + } +} + + +void Info::paintEvent( QPaintEvent *e ) +{ + QPainter p(this); + + BrushStyle styles[] = { Dense1Pattern, Dense2Pattern, Dense3Pattern, + Dense4Pattern, Dense5Pattern, Dense6Pattern }; + + QColor shade = colorGroup().color( QColorGroup::Button ).dark( 110 ); + int blend = width() * 3 / 4; + int step = blend/6; + p.fillRect( 0, 0, width()-blend, 30, shade ); + for ( int i = 0; i < 6; i++ ) { + QBrush brush( shade, styles[i] ); + p.fillRect( width()-blend+i*step, 0, step, 30, brush ); + } + p.setFont( QFont("Helvetica", 24, QFont::Bold) ); + p.setPen( shade.dark( 140 ) ); + p.drawText( 5, 24, "QPE" ); + int pos = 5 + p.fontMetrics().width( "QPE" ); + QFont f("Helvetica", 10, QFont::Bold); + p.setFont( f ); + p.drawText( pos + 5, 24, QString( "Version " ) + QPE_VERSION ); + + if (!menuHasBeenClicked) { + p.drawText( 5, height()-10, QString( "Click on the " ) ); + int pos = 5 + p.fontMetrics().width( "Click on the " ); + p.drawPixmap( pos, height()-10-14, Resource::loadPixmap( "go" ) ); + p.drawText( pos + 16, height()-10, QString( " logo to start." ) ); + needsClear = TRUE; + } + + if ( info ) { + info->setWidth(&p,width()-10); + info->draw(&p, 5, 35, e->region(), colorGroup()); + } +} + + diff --git a/core/launcher/info.h b/core/launcher/info.h new file mode 100644 index 0000000..317dec5 --- a/dev/null +++ b/core/launcher/info.h @@ -0,0 +1,55 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __INFO_H__ +#define __INFO_H__ + + +#include +#include +#include "background.h" + +class QSimpleRichText; + +class Info : public Background { + Q_OBJECT +public: + Info( Desktop *d ); + void menuClicked( ); + +signals: + void giveInfo( ); + +protected: + void mouseReleaseEvent( QMouseEvent *e ); + void paintEvent( QPaintEvent *pe ); + +private: + QSimpleRichText* info; + bool needsClear; + bool menuHasBeenClicked; +}; + + +extern Info *desktopInfo; + + +#endif // __INFO_H__ + diff --git a/core/launcher/inputmethods.cpp b/core/launcher/inputmethods.cpp new file mode 100644 index 0000000..003dc77 --- a/dev/null +++ b/core/launcher/inputmethods.cpp @@ -0,0 +1,297 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "inputmethods.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_WS_QWS +#include +#include +#endif + +#ifdef SINGLE_APP +#include "handwritingimpl.h" +#include "keyboardimpl.h" +#include "pickboardimpl.h" +#endif + + +/* XPM */ +static const char * tri_xpm[]={ +"9 9 2 1", +"a c #000000", +". c None", +".........", +".........", +".........", +"....a....", +"...aaa...", +"..aaaaa..", +".aaaaaaa.", +".........", +"........."}; + +static const int inputWidgetStyle = QWidget::WStyle_Customize | + QWidget::WStyle_Tool | + QWidget::WStyle_StaysOnTop | + QWidget::WGroupLeader; + +InputMethods::InputMethods( QWidget *parent ) : + QWidget( parent, "InputMethods", WStyle_Tool | WStyle_Customize ) +{ + method = NULL; + + QHBoxLayout *hbox = new QHBoxLayout( this ); + + kbdButton = new QToolButton( this ); + kbdButton->setFocusPolicy(NoFocus); + kbdButton->setToggleButton( TRUE ); + kbdButton->setFixedHeight( 17 ); + kbdButton->setFixedWidth( 32 ); + kbdButton->setAutoRaise( TRUE ); + kbdButton->setUsesBigPixmap( TRUE ); + hbox->addWidget( kbdButton ); + connect( kbdButton, SIGNAL(toggled(bool)), this, SLOT(showKbd(bool)) ); + + kbdChoice = new QToolButton( this ); + kbdChoice->setFocusPolicy(NoFocus); + kbdChoice->setPixmap( QPixmap( (const char **)tri_xpm ) ); + kbdChoice->setFixedHeight( 17 ); + kbdChoice->setFixedWidth( 12 ); + kbdChoice->setAutoRaise( TRUE ); + hbox->addWidget( kbdChoice ); + connect( kbdChoice, SIGNAL(clicked()), this, SLOT(chooseKbd()) ); + + connect( (QPEApplication*)qApp, SIGNAL(clientMoused()), + this, SLOT(resetStates()) ); + + loadInputMethods(); +} + +InputMethods::~InputMethods() +{ +#ifndef SINGLE_APP + QValueList::Iterator mit; + for ( mit = inputMethodList.begin(); mit != inputMethodList.end(); ++mit ) { + int i = (*mit).interface->release(); + (*mit).library->unload(); + delete (*mit).library; + } +#endif +} + +void InputMethods::hideInputMethod() +{ + kbdButton->setOn( FALSE ); +} + +void InputMethods::showInputMethod() +{ + kbdButton->setOn( TRUE ); +} + +void InputMethods::showInputMethod(const QString& name) +{ + int i = 0; + QValueList::Iterator it; + InputMethod *im = 0; + for ( it = inputMethodList.begin(); it != inputMethodList.end(); ++it, i++ ) { + if ( (*it).interface->name() == name ) { + im = &(*it); + break; + } + } + if ( im ) + chooseMethod(im); +} + +void InputMethods::resetStates() +{ + if ( method ) + method->interface->resetState(); +} + +QRect InputMethods::inputRect() const +{ + if ( !method || !method->widget->isVisible() ) + return QRect(); + else + return method->widget->geometry(); +} + +void InputMethods::loadInputMethods() +{ +#ifndef SINGLE_APP + hideInputMethod(); + method = 0; + + QValueList::Iterator mit; + for ( mit = inputMethodList.begin(); mit != inputMethodList.end(); ++mit ) { + (*mit).interface->release(); + (*mit).library->unload(); + delete (*mit).library; + } + inputMethodList.clear(); + + QString path = QPEApplication::qpeDir() + "/plugins/inputmethods"; + QDir dir( path, "lib*.so" ); + QStringList list = dir.entryList(); + QStringList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + InputMethodInterface *iface = 0; + QLibrary *lib = new QLibrary( path + "/" + *it ); + if ( lib->queryInterface( IID_InputMethod, (QUnknownInterface**)&iface ) == QS_OK ) { + InputMethod input; + input.library = lib; + input.interface = iface; + input.widget = input.interface->inputMethod( 0, inputWidgetStyle ); + input.interface->onKeyPress( this, SLOT(sendKey(ushort,ushort,ushort,bool,bool)) ); + inputMethodList.append( input ); + QString lang = getenv( "LANG" ); + QTranslator * trans = new QTranslator(qApp); + QString type = (*it).left( (*it).find(".") ); + QString tfn = QPEApplication::qpeDir()+"/i18n/"+lang+"/"+type+".qm"; + qDebug("tr for inputmethod: %s", tfn.latin1() ); + if ( trans->load( tfn )) + qApp->installTranslator( trans ); + else + delete trans; + } else { + delete lib; + } + } +#else + InputMethod input; + input.interface = new HandwritingImpl(); + input.widget = input.interface->inputMethod( 0, inputWidgetStyle ); + input.interface->onKeyPress( this, SLOT(sendKey(ushort,ushort,ushort,bool,bool)) ); + inputMethodList.append( input ); + input.interface = new KeyboardImpl(); + input.widget = input.interface->inputMethod( 0, inputWidgetStyle ); + input.interface->onKeyPress( this, SLOT(sendKey(ushort,ushort,ushort,bool,bool)) ); + inputMethodList.append( input ); + input.interface = new PickboardImpl(); + input.widget = input.interface->inputMethod( 0, inputWidgetStyle ); + input.interface->onKeyPress( this, SLOT(sendKey(ushort,ushort,ushort,bool,bool)) ); + inputMethodList.append( input ); +#endif + if ( !inputMethodList.isEmpty() ) { + method = &inputMethodList[0]; + kbdButton->setPixmap( *method->interface->icon() ); + } + if ( !inputMethodList.isEmpty() ) + kbdButton->show(); + else + kbdButton->hide(); + if ( inputMethodList.count() > 1 ) + kbdChoice->show(); + else + kbdChoice->hide(); +} + +void InputMethods::chooseKbd() +{ + QPopupMenu pop( this ); + + int i = 0; + QValueList::Iterator it; + for ( it = inputMethodList.begin(); it != inputMethodList.end(); ++it, i++ ) { + pop.insertItem( (*it).interface->name(), i ); + if ( method == &(*it) ) + pop.setItemChecked( i, TRUE ); + } + + QPoint pt = mapToGlobal(kbdChoice->geometry().topRight()); + QSize s = pop.sizeHint(); + pt.ry() -= s.height(); + pt.rx() -= s.width(); + i = pop.exec( pt ); + if ( i == -1 ) + return; + InputMethod *im = &inputMethodList[i]; + chooseMethod(im); +} + +void InputMethods::chooseMethod(InputMethod* im) +{ + if ( im != method ) { + if ( method && method->widget->isVisible() ) + method->widget->hide(); + method = im; + kbdButton->setPixmap( *method->interface->icon() ); + } + if ( !kbdButton->isOn() ) + kbdButton->setOn( TRUE ); + else + showKbd( TRUE ); +} + + +void InputMethods::showKbd( bool on ) +{ + if ( !method ) + return; + + if ( on ) { + method->interface->resetState(); + // HACK... Make the texteditor fit with all input methods + // Input methods should also never use more than about 40% of the screen + int height = QMIN( method->widget->sizeHint().height(), 134 ); + method->widget->resize( qApp->desktop()->width(), height ); + method->widget->move( 0, mapToGlobal( QPoint() ).y() - height ); + method->widget->show(); + } else { + method->widget->hide(); + } + + emit inputToggled( on ); +} + +bool InputMethods::shown() const +{ + return method && method->widget->isVisible(); +} + +QString InputMethods::currentShown() const +{ + return method && method->widget->isVisible() + ? method->interface->name() : QString::null; +} + +void InputMethods::sendKey( ushort unicode, ushort scancode, ushort mod, bool press, bool repeat ) +{ +#if defined(Q_WS_QWS) + QWSServer::sendKeyEvent( unicode, scancode, mod, press, repeat ); +#endif +} diff --git a/core/launcher/inputmethods.h b/core/launcher/inputmethods.h new file mode 100644 index 0000000..286a818 --- a/dev/null +++ b/core/launcher/inputmethods.h @@ -0,0 +1,76 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __INPUT_METHODS_H__ +#define __INPUT_METHODS_H__ + + +#include + +#include +#include + +class QToolButton; +class QLibrary; + +struct InputMethod +{ +#ifndef QT_NO_COMPONENT + QLibrary *library; +#endif + QWidget *widget; + InputMethodInterface *interface; +}; + +class InputMethods : public QWidget +{ + Q_OBJECT +public: + InputMethods( QWidget * ); + ~InputMethods(); + + QRect inputRect() const; + bool shown() const; + QString currentShown() const; // name of interface + void showInputMethod(const QString& id); + void showInputMethod(); + void hideInputMethod(); + void loadInputMethods(); + +signals: + void inputToggled( bool on ); + +private slots: + void chooseKbd(); + void showKbd( bool ); + void resetStates(); + void sendKey( ushort unicode, ushort scancode, ushort modifiers, bool, bool ); + +private: + void chooseMethod(InputMethod* im); + QToolButton *kbdButton; + QToolButton *kbdChoice; + InputMethod *method; + QValueList inputMethodList; +}; + + +#endif // __INPUT_METHODS_H__ + diff --git a/core/launcher/irserver.cpp b/core/launcher/irserver.cpp new file mode 100644 index 0000000..b22e064 --- a/dev/null +++ b/core/launcher/irserver.cpp @@ -0,0 +1,50 @@ +#include "irserver.h" + +#include +#include + +#include +#include + +#include "obexinterface.h" + +#include + +IrServer::IrServer( QObject *parent, const char *name ) + : QObject( parent, name ) +{ + lib = 0; + QString path = QPEApplication::qpeDir() + "/plugins/obex/"; + QDir dir( path, "lib*.so" ); + QStringList list = dir.entryList(); + QStringList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + ObexInterface *iface = 0; + QLibrary *trylib = new QLibrary( path + *it ); + qDebug("trying lib %s", (path + (*it)).latin1() ); + if ( trylib->queryInterface( IID_ObexInterface, (QUnknownInterface**)&iface ) == QS_OK ) { + lib = trylib; + qDebug("found obex lib" ); + QString lang = getenv( "LANG" ); + QTranslator * trans = new QTranslator(qApp); + QString type = (*it).left( (*it).find(".") ); + QString tfn = QPEApplication::qpeDir()+"/i18n/"+lang+"/"+type+".qm"; + qDebug("tr fpr obex: %s", tfn.latin1() ); + if ( trans->load( tfn )) + qApp->installTranslator( trans ); + else + delete trans; + + break; + } else { + delete lib; + } + } + if ( !lib ) + qDebug("could not load IR plugin" ); +} + +IrServer::~IrServer() +{ + delete lib; +} diff --git a/core/launcher/irserver.h b/core/launcher/irserver.h new file mode 100644 index 0000000..f9f682f --- a/dev/null +++ b/core/launcher/irserver.h @@ -0,0 +1,20 @@ +#ifndef IRSERVER_H +#define IRSERVER_H + +#include + +class QCopChannel; +class QLibrary; + +class IrServer : public QObject +{ + Q_OBJECT +public: + IrServer( QObject *parent = 0, const char *name = 0 ); + ~IrServer(); + +private: + QLibrary *lib; +}; + +#endif diff --git a/core/launcher/launcher.cpp b/core/launcher/launcher.cpp new file mode 100644 index 0000000..66a2ce5 --- a/dev/null +++ b/core/launcher/launcher.cpp @@ -0,0 +1,804 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "launcherview.h" +#include "launcher.h" +#include "syncdialog.h" +#include "desktop.h" +#include +#include "mrulist.h" +#include "qrsync.h" +#include +#include + +#if defined(_OS_LINUX_) || defined(Q_OS_LINUX) +#include +#include +#include +#endif + +//#define SHOW_ALL + +CategoryTabWidget::CategoryTabWidget( QWidget* parent ) : + QVBox( parent ) +{ + categoryBar = 0; + stack = 0; +} + +void CategoryTabWidget::prevTab() +{ + if ( categoryBar ) { + int n = categoryBar->count(); + int tab = categoryBar->currentTab(); + if ( tab >= 0 ) + categoryBar->setCurrentTab( (tab - 1 + n)%n ); + } +} + +void CategoryTabWidget::nextTab() +{ + if ( categoryBar ) { + int n = categoryBar->count(); + int tab = categoryBar->currentTab(); + categoryBar->setCurrentTab( (tab + 1)%n ); + } +} + +void CategoryTabWidget::addItem( const QString& linkfile ) +{ + int i=0; + AppLnk *app = new AppLnk(linkfile); + if ( !app->isValid() ) { + delete app; + return; + } + if ( !app->file().isEmpty() ) { + // A document + delete app; + app = new DocLnk(linkfile); + ((LauncherView*)(stack->widget(ids.count()-1)))->addItem(app); + return; + } + for ( QStringList::Iterator it=ids.begin(); it!=ids.end(); ++it) { + if ( !(*it).isEmpty() ) { + QRegExp tf(*it,FALSE,TRUE); + if ( tf.match(app->type()) >= 0 ) { + ((LauncherView*)stack->widget(i))->addItem(app); + return; + } + i++; + } + } +} + +void CategoryTabWidget::initializeCategories(AppLnkSet* rootFolder, + AppLnkSet* docFolder, const QList &fs) +{ + delete categoryBar; + categoryBar = new CategoryTabBar( this ); + QPalette pal = categoryBar->palette(); + pal.setColor( QColorGroup::Light, pal.color(QPalette::Active,QColorGroup::Shadow) ); + pal.setColor( QColorGroup::Background, pal.active().background().light(110) ); + categoryBar->setPalette( pal ); + + delete stack; + stack = new QWidgetStack(this); + tabs=0; + + ids.clear(); + + QStringList types = rootFolder->types(); + for ( QStringList::Iterator it=types.begin(); it!=types.end(); ++it) { + if ( !(*it).isEmpty() ) { + newView(*it,rootFolder->typePixmap(*it),rootFolder->typeName(*it)); + } + } + QListIterator it( rootFolder->children() ); + AppLnk* l; + while ( (l=it.current()) ) { + if ( l->type() == "Separator" ) { + rootFolder->remove(l); + delete l; + } else { + int i=0; + for ( QStringList::Iterator it=types.begin(); it!=types.end(); ++it) { + if ( *it == l->type() ) + ((LauncherView*)stack->widget(i))->addItem(l,FALSE); + i++; + } + } + ++it; + } + rootFolder->detachChildren(); + for (int i=0; iwidget(i))->sort(); + + // all documents + docview = newView( QString::null, Resource::loadPixmap("DocsIcon"), tr("Documents")); + docview->populate( docFolder, QString::null ); + docFolder->detachChildren(); + docview->setFileSystems(fs); + docview->setToolsEnabled(TRUE); + + connect( categoryBar, SIGNAL(selected(int)), stack, SLOT(raiseWidget(int)) ); + + ((LauncherView*)stack->widget(0))->setFocus(); + + categoryBar->show(); + stack->show(); +} + +void CategoryTabWidget::updateDocs(AppLnkSet* docFolder, const QList &fs) +{ + docview->populate( docFolder, QString::null ); + docFolder->detachChildren(); + docview->setFileSystems(fs); + docview->updateTools(); +} + +LauncherView* CategoryTabWidget::newView( const QString& id, const QPixmap& pm, const QString& label ) +{ + LauncherView* view = new LauncherView( stack ); + connect( view, SIGNAL(clicked(const AppLnk*)), + this, SIGNAL(clicked(const AppLnk*))); + connect( view, SIGNAL(rightPressed(AppLnk*)), + this, SIGNAL(rightPressed(AppLnk*))); + ids.append(id); + categoryBar->addTab( new QTab( pm, label ) ); + stack->addWidget( view, tabs++ ); + return view; +} + +void CategoryTabWidget::updateLink(const QString& linkfile) +{ + int i=0; + LauncherView* view; + while ((view = (LauncherView*)stack->widget(i++))) { + if ( view->removeLink(linkfile) ) + break; + } + addItem(linkfile); + docview->updateTools(); +} + +void CategoryTabWidget::paletteChange( const QPalette &p ) +{ + QVBox::paletteChange( p ); + QPalette pal = palette(); + pal.setColor( QColorGroup::Light, pal.color(QPalette::Active,QColorGroup::Shadow) ); + pal.setColor( QColorGroup::Background, pal.active().background().light(110) ); + categoryBar->setPalette( pal ); + categoryBar->update(); +} + +void CategoryTabWidget::setBusy(bool on) +{ + if ( on ) + ((LauncherView*)stack->visibleWidget())->setBusy(TRUE); + else + for (int i=0; iwidget(i))->setBusy(FALSE); +} + + +CategoryTabBar::CategoryTabBar( QWidget *parent, const char *name ) + : QTabBar( parent, name ) +{ + setFocusPolicy( NoFocus ); + connect( this, SIGNAL( selected(int) ), this, SLOT( layoutTabs() ) ); +} + +CategoryTabBar::~CategoryTabBar() +{ +} + +void CategoryTabBar::layoutTabs() +{ + if ( !count() ) + return; + +// int percentFalloffTable[] = { 100, 70, 40, 12, 6, 3, 1, 0 }; + int hiddenTabWidth = -12; + int middleTab = currentTab(); + int hframe, vframe, overlap; + style().tabbarMetrics( this, hframe, vframe, overlap ); + QFontMetrics fm = fontMetrics(); + int x = 0; + QRect r; + QTab *t; + int available = width()-1; + int required = 0; + for ( int i = 0; i < count(); i++ ) { + t = tab(i); + // if (( i < (middleTab - 1) ) || ( i > (middleTab + 1) )) { + if ( i != middleTab ) { + // required += hiddenTabWidth + hframe - overlap; + available -= hiddenTabWidth + hframe - overlap; + if ( t->iconSet() != 0 ) + available -= t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width(); + } else { + required += fm.width( t->text() ) + hframe - overlap; + if ( t->iconSet() != 0 ) + required += t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width(); + } + } + for ( int i = 0; i < count(); i++ ) { + t = tab(i); + // if (( i < (middleTab - 1) ) || ( i > (middleTab + 1) )) { + if ( i != middleTab ) { + int w = hiddenTabWidth; + int ih = 0; + if ( t->iconSet() != 0 ) { + w += t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width(); + ih = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).height(); + } + int h = QMAX( fm.height(), ih ); + h = QMAX( h, QApplication::globalStrut().height() ); + + h += vframe; + w += hframe; + + t->setRect( QRect(x, 0, w, h) ); + x += t->rect().width() - overlap; + r = r.unite( t->rect() ); + } else { + int w = fm.width( t->text() ); + int ih = 0; + if ( t->iconSet() != 0 ) { + w += t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width(); + ih = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).height(); + } + int h = QMAX( fm.height(), ih ); + h = QMAX( h, QApplication::globalStrut().height() ); + + h += vframe; + w += hframe; + + // t->setRect( QRect(x, 0, w * available/required, h) ); + t->setRect( QRect(x, 0, available, h) ); + x += t->rect().width() - overlap; + r = r.unite( t->rect() ); + } + } + + QRect rr = tab(count()-1)->rect(); + rr.setRight(width()-1); + tab(count()-1)->setRect( rr ); + + for ( t = tabList()->first(); t; t = tabList()->next() ) { + QRect tr = t->rect(); + tr.setHeight( r.height() ); + t->setRect( tr ); + } + + update(); +} + + +void CategoryTabBar::paint( QPainter * p, QTab * t, bool selected ) const +{ +#if QT_VERSION >= 300 + QStyle::SFlags flags = QStyle::Style_Default; + if ( selected ) + flags |= QStyle::Style_Selected; + style().drawControl( QStyle::CE_TabBarTab, p, this, t->rect(), + colorGroup(), flags, QStyleOption(t) ); +#else + style().drawTab( p, this, t, selected ); +#endif + + QRect r( t->rect() ); + QFont f( font() ); + if ( selected ) + f.setBold( TRUE ); + p->setFont( f ); + + int iw = 0; + int ih = 0; + if ( t->iconSet() != 0 ) { + iw = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 2; + ih = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).height(); + } + int w = iw + p->fontMetrics().width( t->text() ) + 4; + int h = QMAX(p->fontMetrics().height() + 4, ih ); + paintLabel( p, QRect( r.left() + (r.width()-w)/2 - 3, + r.top() + (r.height()-h)/2, w, h ), t, +#if QT_VERSION >= 300 + t->identifier() == keyboardFocusTab() +#else + t->identitifer() == keyboardFocusTab() +#endif + ); +} + + +void CategoryTabBar::paintLabel( QPainter* p, const QRect&, + QTab* t, bool has_focus ) const +{ + QRect r = t->rect(); + // if ( t->id != currentTab() ) + //r.moveBy( 1, 1 ); + // + if ( t->iconSet() ) { + // the tab has an iconset, draw it in the right mode + QIconSet::Mode mode = (t->isEnabled() && isEnabled()) ? QIconSet::Normal : QIconSet::Disabled; + if ( mode == QIconSet::Normal && has_focus ) + mode = QIconSet::Active; + QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, mode ); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + p->drawPixmap( r.left() + 6, r.center().y() - pixh / 2 + 1, pixmap ); + r.setLeft( r.left() + pixw + 5 ); + } + + QRect tr = r; + + if ( r.width() < 20 ) + return; + + if ( t->isEnabled() && isEnabled() ) { +#if defined(_WS_WIN32_) + if ( colorGroup().brush( QColorGroup::Button ) == colorGroup().brush( QColorGroup::Background ) ) + p->setPen( colorGroup().buttonText() ); + else + p->setPen( colorGroup().foreground() ); +#else + p->setPen( colorGroup().foreground() ); +#endif + p->drawText( tr, AlignCenter | AlignVCenter | ShowPrefix, t->text() ); + } else { + p->setPen( palette().disabled().foreground() ); + p->drawText( tr, AlignCenter | AlignVCenter | ShowPrefix, t->text() ); + } +} + +//--------------------------------------------------------------------------- + +Launcher::Launcher( QWidget* parent, const char* name, WFlags fl ) + : QMainWindow( parent, name, fl ) +{ + setCaption( tr("Launcher") ); + + syncDialog = 0; + + // we have a pretty good idea how big we'll be + setGeometry( 0, 0, qApp->desktop()->width(), qApp->desktop()->height() ); + + tabs = 0; + rootFolder = 0; + docsFolder = 0; + + tabs = new CategoryTabWidget( this ); + tabs->setMaximumWidth( qApp->desktop()->width() ); + setCentralWidget( tabs ); + + connect( tabs, SIGNAL(selected(const QString&)), + this, SLOT(viewSelected(const QString&)) ); + connect( tabs, SIGNAL(clicked(const AppLnk*)), + this, SLOT(select(const AppLnk*))); + connect( tabs, SIGNAL(rightPressed(AppLnk*)), + this, SLOT(properties(AppLnk*))); + +#if defined(Q_WS_QWS) && !defined(QT_NO_COP) + QCopChannel* sysChannel = new QCopChannel( "QPE/System", this ); + connect( sysChannel, SIGNAL(received(const QCString &, const QByteArray &)), + this, SLOT(systemMessage( const QCString &, const QByteArray &)) ); +#endif + + storage = new StorageInfo( this ); + connect( storage, SIGNAL( disksChanged() ), SLOT( storageChanged() ) ); + + updateTabs(); + + preloadApps(); + + in_lnk_props = FALSE; + got_lnk_change = FALSE; +} + +Launcher::~Launcher() +{ +} + +static bool isVisibleWindow(int wid) +{ + const QList &list = qwsServer->clientWindows(); + QWSWindow* w; + for (QListIterator it(list); (w=it.current()); ++it) { + if ( w->winId() == wid ) + return !w->isFullyObscured(); + } + return FALSE; +} + +void Launcher::showMaximized() +{ + if ( isVisibleWindow( winId() ) ) + doMaximize(); + else + QTimer::singleShot( 20, this, SLOT(doMaximize()) ); +} + +void Launcher::doMaximize() +{ + QMainWindow::showMaximized(); +} + +void Launcher::updateMimeTypes() +{ + MimeType::clear(); + updateMimeTypes(rootFolder); +} + +void Launcher::updateMimeTypes(AppLnkSet* folder) +{ + for ( QListIterator it( folder->children() ); it.current(); ++it ) { + AppLnk *app = it.current(); + if ( app->type() == "Folder" ) + updateMimeTypes((AppLnkSet *)app); + else { + MimeType::registerApp(*app); + } + } +} + +void Launcher::loadDocs() +{ + delete docsFolder; + docsFolder = new DocLnkSet; + Global::findDocuments(docsFolder); +} + +void Launcher::updateTabs() +{ + MimeType::updateApplications(); // ### reads all applnks twice + + delete rootFolder; + rootFolder = new AppLnkSet( MimeType::appsFolderName() ); + + loadDocs(); + + tabs->initializeCategories(rootFolder, docsFolder, storage->fileSystems()); +} + +void Launcher::updateDocs() +{ + loadDocs(); + tabs->updateDocs(docsFolder,storage->fileSystems()); +} + +void Launcher::viewSelected(const QString& s) +{ + setCaption( s + tr(" - Launcher") ); +} + +void Launcher::nextView() +{ + tabs->nextTab(); +} + + +void Launcher::select( const AppLnk *appLnk ) +{ + if ( appLnk->type() == "Folder" ) { + // Not supported: flat is simpler for the user + } else { + if ( appLnk->exec().isNull() ) { + QMessageBox::information(this,tr("No application"), + tr("

No application is defined for this document." + "

Type is %1.").arg(appLnk->type())); + return; + } + tabs->setBusy(TRUE); + emit executing( appLnk ); + appLnk->execute(); + } +} + +void Launcher::externalSelected(const AppLnk *appLnk) +{ + tabs->setBusy(TRUE); + emit executing( appLnk ); +} + +void Launcher::properties( AppLnk *appLnk ) +{ + if ( appLnk->type() == "Folder" ) { + // Not supported: flat is simpler for the user + } else { + in_lnk_props = TRUE; + got_lnk_change = FALSE; + LnkProperties prop(appLnk); + connect(&prop, SIGNAL(select(const AppLnk *)), this, SLOT(externalSelected(const AppLnk *))); + prop.showMaximized(); + prop.exec(); + in_lnk_props = FALSE; + if ( got_lnk_change ) { + updateLink(lnk_change); + } + } +} + +void Launcher::updateLink(const QString& link) +{ + if (link.isNull()) + updateTabs(); + else if (link.isEmpty()) + updateDocs(); + else + tabs->updateLink(link); +} + +void Launcher::systemMessage( const QCString &msg, const QByteArray &data) +{ + QDataStream stream( data, IO_ReadOnly ); + if ( msg == "linkChanged(QString)" ) { + QString link; + stream >> link; + if ( in_lnk_props ) { + got_lnk_change = TRUE; + lnk_change = link; + } else { + updateLink(link); + } + } else if ( msg == "busy()" ) { + emit busy(); + } else if ( msg == "notBusy(QString)" ) { + QString app; + stream >> app; + tabs->setBusy(FALSE); + emit notBusy(app); + } else if ( msg == "mkdir(QString)" ) { + QString dir; + stream >> dir; + if ( !dir.isEmpty() ) + mkdir( dir ); + } else if ( msg == "rdiffGenSig(QString,QString)" ) { + QString baseFile, sigFile; + stream >> baseFile >> sigFile; + QRsync::generateSignature( baseFile, sigFile ); + } else if ( msg == "rdiffGenDiff(QString,QString,QString)" ) { + QString baseFile, sigFile, deltaFile; + stream >> baseFile >> sigFile >> deltaFile; + QRsync::generateDiff( baseFile, sigFile, deltaFile ); + } else if ( msg == "rdiffApplyPatch(QString,QString)" ) { + QString baseFile, deltaFile; + stream >> baseFile >> deltaFile; + if ( !QFile::exists( baseFile ) ) { + QFile f( baseFile ); + f.open( IO_WriteOnly ); + f.close(); + } + QRsync::applyDiff( baseFile, deltaFile ); + QCopEnvelope e( "QPE/Desktop", "patchApplied(QString)" ); + e << baseFile; + } else if ( msg == "rdiffCleanup()" ) { + mkdir( "/tmp/rdiff" ); + QDir dir; + dir.setPath( "/tmp/rdiff" ); + QStringList entries = dir.entryList(); + for ( QStringList::Iterator it = entries.begin(); it != entries.end(); ++it ) + dir.remove( *it ); + } else if ( msg == "sendHandshakeInfo()" ) { + QString home = getenv( "HOME" ); + QCopEnvelope e( "QPE/Desktop", "handshakeInfo(QString,bool)" ); + e << home; + int locked = (int) Desktop::screenLocked(); + e << locked; + } else if ( msg == "sendCardInfo()" ) { + QCopEnvelope e( "QPE/Desktop", "cardInfo(QString)" ); + const QList &fs = storage->fileSystems(); + QListIterator it ( fs ); + QString s; + QString homeDir = getenv("HOME"); + QString hardDiskHome; + for ( ; it.current(); ++it ) { + if ( (*it)->isRemovable() ) + s += (*it)->name() + "=" + (*it)->path() + "/Documents " + + QString::number( (*it)->availBlocks() * (*it)->blockSize() ) + + " " + (*it)->options() + ";"; + else if ( (*it)->disk() == "/dev/mtdblock1" || + (*it)->disk() == "/dev/mtdblock/1" ) + s += (*it)->name() + "=" + homeDir + "/Documents " + + QString::number( (*it)->availBlocks() * (*it)->blockSize() ) + + " " + (*it)->options() + ";"; + else if ( (*it)->name().contains( "Hard Disk") && + homeDir.contains( (*it)->path() ) && + (*it)->path().length() > hardDiskHome.length() ) + hardDiskHome = + (*it)->name() + "=" + homeDir + "/Documents " + + QString::number( (*it)->availBlocks() * (*it)->blockSize() ) + + " " + (*it)->options() + ";"; + } + if ( !hardDiskHome.isEmpty() ) + s += hardDiskHome; + + e << s; + } else if ( msg == "sendSyncDate(QString)" ) { + QString app; + stream >> app; + Config cfg( "qpe" ); + cfg.setGroup("SyncDate"); + QCopEnvelope e( "QPE/Desktop", "syncDate(QString,QString)" ); + e << app << cfg.readEntry( app ); + //qDebug("QPE/System sendSyncDate for %s: response %s", app.latin1(), + //cfg.readEntry( app ).latin1() ); + } else if ( msg == "setSyncDate(QString,QString)" ) { + QString app, date; + stream >> app >> date; + Config cfg( "qpe" ); + cfg.setGroup("SyncDate"); + cfg.writeEntry( app, date ); + //qDebug("setSyncDate(QString,QString) %s %s", app.latin1(), date.latin1()); + } else if ( msg == "startSync(QString)" ) { + QString what; + stream >> what; + delete syncDialog; syncDialog = 0; + syncDialog = new SyncDialog( this, "syncProgress", FALSE, + WStyle_Tool | WStyle_Customize | + Qt::WStyle_StaysOnTop ); + syncDialog->showMaximized(); + syncDialog->whatLabel->setText( "" + what + "" ); + connect( syncDialog->buttonCancel, SIGNAL( clicked() ), + SLOT( cancelSync() ) ); + } + else if ( msg == "stopSync()") { + delete syncDialog; syncDialog = 0; + } else if ( msg == "getAllDocLinks()" ) { + loadDocs(); + + QString contents; + + for ( QListIterator it( docsFolder->children() ); it.current(); ++it ) { + DocLnk *doc = it.current(); + QString lfn = doc->linkFile(); + QFileInfo fi( doc->file() ); + if ( !fi.exists() ) + continue; + + + + QFile f( lfn ); + if ( f.open( IO_ReadOnly ) ) { + QTextStream ts( &f ); + ts.setEncoding( QTextStream::UnicodeUTF8 ); + contents += ts.read(); + f.close(); + } else { + contents += "[Desktop Entry]\n"; + contents += "Categories = " + Qtopia::Record::idsToString( doc->categories() ) + "\n"; + contents += "File = "+doc->file()+"\n"; + contents += "Name = "+doc->name()+"\n"; + contents += "Type = "+doc->type()+"\n"; + } + contents += QString("Size = %1\n").arg( fi.size() ); + } + + //qDebug( "sending length %d", contents.length() ); + QCopEnvelope e( "QPE/Desktop", "docLinks(QString)" ); + e << contents; + + //qDebug( "================ \n\n%s\n\n===============", + //contents.latin1() ); + + delete docsFolder; + docsFolder = 0; + } +} + +void Launcher::cancelSync() +{ + QCopEnvelope e( "QPE/Desktop", "cancelSync()" ); +} + +void Launcher::storageChanged() +{ + if ( in_lnk_props ) { + got_lnk_change = TRUE; + lnk_change = ""; + } else { + updateDocs(); + } +} + + +bool Launcher::mkdir(const QString &localPath) +{ + QDir fullDir(localPath); + if (fullDir.exists()) + return true; + + // at this point the directory doesn't exist + // go through the directory tree and start creating the direcotories + // that don't exist; if we can't create the directories, return false + + QString dirSeps = "/"; + int dirIndex = localPath.find(dirSeps); + QString checkedPath; + + // didn't find any seps; weird, use the cur dir instead + if (dirIndex == -1) { + //qDebug("No seperators found in path %s", localPath.latin1()); + checkedPath = QDir::currentDirPath(); + } + + while (checkedPath != localPath) { + // no more seperators found, use the local path + if (dirIndex == -1) + checkedPath = localPath; + else { + // the next directory to check + checkedPath = localPath.left(dirIndex) + "/"; + // advance the iterator; the next dir seperator + dirIndex = localPath.find(dirSeps, dirIndex+1); + } + + QDir checkDir(checkedPath); + if (!checkDir.exists()) { + //qDebug("mkdir making dir %s", checkedPath.latin1()); + + if (!checkDir.mkdir(checkedPath)) { + qDebug("Unable to make directory %s", checkedPath.latin1()); + return FALSE; + } + } + + } + return TRUE; +} + +void Launcher::preloadApps() +{ + Config cfg("Launcher"); + cfg.setGroup("Preload"); + QStringList apps = cfg.readListEntry("Apps",','); + for (QStringList::ConstIterator it=apps.begin(); it!=apps.end(); ++it) { + QCopEnvelope e("QPE/Application/"+(*it).local8Bit(), "enablePreload()"); + } +} diff --git a/core/launcher/launcher.h b/core/launcher/launcher.h new file mode 100644 index 0000000..00ae980 --- a/dev/null +++ b/core/launcher/launcher.h @@ -0,0 +1,136 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef LAUNCHER_H +#define LAUNCHER_H + +#include +#include +#include +#include +#include +#include "launcherview.h" + +class AppLnk; +class AppLnkSet; +class DocLnkSet; +class QWidgetStack; +class StorageInfo; +class SyncDialog; + +class CategoryTabBar : public QTabBar +{ + Q_OBJECT +public: + CategoryTabBar( QWidget *parent=0, const char *name=0 ); + ~CategoryTabBar(); + +protected slots: + virtual void layoutTabs(); + +protected: + void paint ( QPainter *p, QTab *t, bool f ) const; + void paintLabel( QPainter* p, const QRect& br, QTab* t, bool has_focus ) const; +}; + +class CategoryTabWidget : public QVBox { + // can't use a QTabWidget, since it won't let us set the frame style. + Q_OBJECT +public: + CategoryTabWidget( QWidget* parent ); + void initializeCategories(AppLnkSet* rootFolder, AppLnkSet* docFolder, + const QList &); + void updateDocs(AppLnkSet* docFolder, const QList &fs); + void updateLink(const QString& linkfile); + void setBusy(bool on); + +signals: + void selected(const QString&); + void clicked(const AppLnk*); + void rightPressed(AppLnk*); + +public slots: + void nextTab(); + void prevTab(); + +protected: + void paletteChange( const QPalette &p ); + +private: + CategoryTabBar* categoryBar; + QWidgetStack* stack; + LauncherView* docview; + QStringList ids; + int tabs; + LauncherView* newView( const QString&, const QPixmap& pm, const QString& label ); + void addItem( const QString& ); +}; + +class Launcher : public QMainWindow +{ + Q_OBJECT + friend class LauncherPrivate; +public: + Launcher( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~Launcher(); + + static QString appsFolderName(); + + virtual void showMaximized(); + static bool mkdir(const QString &path); + +public slots: + void viewSelected(const QString&); + void select( const AppLnk * ); + void externalSelected( const AppLnk *); + void properties( AppLnk * ); + void nextView(); + +signals: + void executing( const AppLnk * ); + void busy(); + void notBusy(const QString&); + +private slots: + void doMaximize(); + void systemMessage( const QCString &, const QByteArray &); + void storageChanged(); + void cancelSync(); + +private: + void updateApps(); + void loadDocs(); + void updateDocs(); + void updateTabs(); + void updateMimeTypes(); + void updateMimeTypes(AppLnkSet*); + void preloadApps(); + AppLnkSet *rootFolder; + DocLnkSet *docsFolder; + CategoryTabWidget *tabs; + StorageInfo *storage; + SyncDialog *syncDialog; + + void updateLink(const QString& link); + bool in_lnk_props; + bool got_lnk_change; + QString lnk_change; +}; + +#endif // LAUNCHERVIEW_H diff --git a/core/launcher/launcher.pro b/core/launcher/launcher.pro new file mode 100644 index 0000000..7d7c9ac --- a/dev/null +++ b/core/launcher/launcher.pro @@ -0,0 +1,110 @@ +TEMPLATE = app + +CONFIG = qt warn_on release + +DESTDIR = $(QPEDIR)/bin + +HEADERS = background.h \ + desktop.h \ + info.h \ + appicons.h \ + taskbar.h \ + sidething.h \ + mrulist.h \ + stabmon.h \ + inputmethods.h \ + systray.h \ + wait.h \ + shutdownimpl.h \ + launcher.h \ + launcherview.h \ + ../calibrate/calibrate.h \ + startmenu.h \ + transferserver.h \ + qcopbridge.h \ + packageslave.h \ + irserver.h \ + $(QPEDIR)/rsync/buf.h \ + $(QPEDIR)/rsync/checksum.h \ + $(QPEDIR)/rsync/command.h \ + $(QPEDIR)/rsync/emit.h \ + $(QPEDIR)/rsync/job.h \ + $(QPEDIR)/rsync/netint.h \ + $(QPEDIR)/rsync/protocol.h \ + $(QPEDIR)/rsync/prototab.h \ + $(QPEDIR)/rsync/rsync.h \ + $(QPEDIR)/rsync/search.h \ + $(QPEDIR)/rsync/stream.h \ + $(QPEDIR)/rsync/sumset.h \ + $(QPEDIR)/rsync/trace.h \ + $(QPEDIR)/rsync/types.h \ + $(QPEDIR)/rsync/util.h \ + $(QPEDIR)/rsync/whole.h \ + $(QPEDIR)/rsync/config_rsync.h \ + $(QPEDIR)/rsync/qrsync.h +# quicklauncher.h \ + +SOURCES = background.cpp \ + desktop.cpp \ + info.cpp \ + appicons.cpp \ + taskbar.cpp \ + sidething.cpp \ + mrulist.cpp \ + stabmon.cpp \ + inputmethods.cpp \ + systray.cpp \ + wait.cpp \ + shutdownimpl.cpp \ + launcher.cpp \ + launcherview.cpp \ + $(QPEDIR)/calibrate/calibrate.cpp \ + transferserver.cpp \ + packageslave.cpp \ + irserver.cpp \ + qcopbridge.cpp \ + startmenu.cpp \ + main.cpp \ + $(QPEDIR)/rsync/base64.c \ + $(QPEDIR)/rsync/buf.c \ + $(QPEDIR)/rsync/checksum.c \ + $(QPEDIR)/rsync/command.c \ + $(QPEDIR)/rsync/delta.c \ + $(QPEDIR)/rsync/emit.c \ + $(QPEDIR)/rsync/hex.c \ + $(QPEDIR)/rsync/job.c \ + $(QPEDIR)/rsync/mdfour.c \ + $(QPEDIR)/rsync/mksum.c \ + $(QPEDIR)/rsync/msg.c \ + $(QPEDIR)/rsync/netint.c \ + $(QPEDIR)/rsync/patch.c \ + $(QPEDIR)/rsync/prototab.c \ + $(QPEDIR)/rsync/readsums.c \ + $(QPEDIR)/rsync/scoop.c \ + $(QPEDIR)/rsync/search.c \ + $(QPEDIR)/rsync/stats.c \ + $(QPEDIR)/rsync/stream.c \ + $(QPEDIR)/rsync/sumset.c \ + $(QPEDIR)/rsync/trace.c \ + $(QPEDIR)/rsync/tube.c \ + $(QPEDIR)/rsync/util.c \ + $(QPEDIR)/rsync/version.c \ + $(QPEDIR)/rsync/whole.c \ + $(QPEDIR)/rsync/qrsync.cpp + +INTERFACES = shutdown.ui syncdialog.ui + +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include . + +INCLUDEPATH += $(QPEDIR)/calibrate +DEPENDPATH += $(QPEDIR)/calibrate + +INCLUDEPATH += $(QPEDIR)/rsync +DEPENDPATH += $(QPEDIR)/rsync + +TARGET = qpe + +LIBS += -lqpe -lcrypt + +TRANSLATIONS = ../i18n/de/qpe.ts diff --git a/core/launcher/launcherview.cpp b/core/launcher/launcherview.cpp new file mode 100644 index 0000000..68e3245 --- a/dev/null +++ b/core/launcher/launcherview.cpp @@ -0,0 +1,596 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "launcherview.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class LauncherIconView : public QIconView { +public: + LauncherIconView( QWidget* parent, const char* name=0 ) : + QIconView(parent,name), + tf(""), + cf(0), + bsy(0) + { + sortmeth = Name; + hidden.setAutoDelete(TRUE); + ike = FALSE; + } + + ~LauncherIconView() + { +#if 0 // debuggery + QListIterator it(hidden); + AppLnk* l; + while ((l=it.current())) { + ++it; + //qDebug("%p: hidden (should remove)",l); + } +#endif + } + + QIconViewItem* busyItem() const { return bsy; } + + void updateCategoriesAndMimeTypes(); + + void doAutoScroll() + { + // We don't want rubberbanding (yet) + } + + void setBusy(bool on) + { + QIconViewItem *c = on ? currentItem() : 0; + if ( bsy != c ) { + QIconViewItem* o = bsy; + bsy = c; + if ( o ) o->repaint(); + if ( c ) c->repaint(); + } + } + + bool inKeyEvent() const { return ike; } + void keyPressEvent(QKeyEvent* e) + { + ike = TRUE; + if ( e->key() == Key_F33 ) { + // "OK" button + returnPressed(currentItem()); + } + QIconView::keyPressEvent(e); + ike = FALSE; + } + + void addItem(AppLnk* app, bool resort=TRUE); + bool removeLink(const QString& linkfile); + + QStringList mimeTypes() const; + QStringList categories() const; + + void clear() + { + mimes.clear(); + cats.clear(); + QIconView::clear(); + hidden.clear(); + } + + void addCatsAndMimes(AppLnk* app) + { + // QStringList c = app->categories(); + // for (QStringList::ConstIterator cit=c.begin(); cit!=c.end(); ++cit) { + // cats.replace(*cit,(void*)1); + // } + QString maj=app->type(); + int sl=maj.find('/'); + if (sl>=0) { + QString k = maj.left(sl); + mimes.replace(k,(void*)1); + } + } + + void drawBackground( QPainter *p, const QRect &r ) + { + // int backgroundMode = QPixmap::defaultDepth() >= 12 ? 1 : 0; + int backgroundMode = 2; + + if ( backgroundMode == 1 ) { + + // Double buffer the background + static QPixmap *bg = NULL; + static QColor bgColor; + + if ( (bg == NULL) || (bgColor != colorGroup().button()) ) { + // Create a new background double buffer + if (bg == NULL) + bg = new QPixmap( width(), height() ); + bgColor = colorGroup().button(); + QPainter painter( bg ); + + painter.fillRect( QRect( 0, 0, width(), height() ), QBrush( white ) ); + + // Overlay the Qtopia logo in the center + QImage logo = Resource::loadImage( "qpe-logo" ); + if ( !logo.isNull() ) + painter.drawImage( (width() - logo.width()) / 2, + (height() - logo.height()) / 2, logo ); + } + + // Draw the double buffer to the widget (it is tiled for when the icon view is large) + p->drawTiledPixmap( r, *bg, QPoint( (r.x() + contentsX()) % bg->width(), + (r.y() + contentsY()) % bg->height() ) ); + } else if ( backgroundMode == 2 ) { + static QPixmap *bg = 0; + static QColor bgColor; + if ( !bg || (bgColor != colorGroup().background()) ) { + bgColor = colorGroup().background(); + bg = new QPixmap( width(), 9 ); + QPainter painter( bg ); + for ( int i = 0; i < 3; i++ ) { + painter.setPen( white ); + painter.drawLine( 0, i*3, width()-1, i*3 ); + painter.drawLine( 0, i*3+1, width()-1, i*3+1 ); + painter.setPen( colorGroup().background().light(105) ); + painter.drawLine( 0, i*3+2, width()-1, i*3+2 ); + } + } + p->drawTiledPixmap( r, *bg, QPoint( (r.x() + contentsX()) % bg->width(), + (r.y() + contentsY()) % bg->height() ) ); + } else { + p->fillRect( r, QBrush( white ) ); + } + } + + void hideOrShowItems(bool resort); + + void setTypeFilter(const QString& typefilter, bool resort) + { + tf = QRegExp(typefilter,FALSE,TRUE); + hideOrShowItems(resort); + } + + void setCategoryFilter( int catfilter, bool resort ) + { + Categories cat; + cat.load( categoryFileName() ); + QString str; + if ( catfilter == -2 ) + cf = 0; + else + cf = catfilter; + hideOrShowItems(resort); + } + + enum SortMethod { Name, Date, Type }; + + void setSortMethod( SortMethod m ) + { + if ( sortmeth != m ) { + sortmeth = m; + sort(); + } + } + + int compare(const AppLnk* a, const AppLnk* b) + { + switch (sortmeth) { + case Name: + return a->name().compare(b->name()); + case Date: { + QFileInfo fa(a->linkFile()); + if ( !fa.exists() ) fa.setFile(a->file()); + QFileInfo fb(b->linkFile()); + if ( !fb.exists() ) fb.setFile(b->file()); + return fa.lastModified().secsTo(fb.lastModified()); + } + case Type: + return a->type().compare(b->type()); + } + return 0; + } + +protected: + + void styleChange( QStyle &old ) + { + QIconView::styleChange( old ); + //### duplicated code from LauncherView constructor + int dw = QApplication::desktop()->width(); + setGridX( (dw-13-style().scrollBarExtent().width())/3 ); // tweaked for 8pt+dw=176 and 10pt+dw=240 + } + +private: + QList hidden; + QDict mimes; + QDict cats; + SortMethod sortmeth; + QRegExp tf; + int cf; + QIconViewItem* bsy; + bool ike; + +}; + + +bool LauncherView::bsy=FALSE; + +void LauncherView::setBusy(bool on) +{ + icons->setBusy(on); +} + +class LauncherItem : public QIconViewItem +{ +public: + LauncherItem( QIconView *parent, AppLnk* applnk ); + ~LauncherItem() + { + LauncherIconView* liv = (LauncherIconView*)iconView(); + if ( liv->busyItem() == this ) + liv->setBusy(FALSE); + delete app; + } + + AppLnk* appLnk() const { return app; } + AppLnk* takeAppLnk() { AppLnk* r=app; app=0; return r; } + + virtual int compare ( QIconViewItem * i ) const; + + void paintItem( QPainter *p, const QColorGroup &cg ) + { + LauncherIconView* liv = (LauncherIconView*)iconView(); + QBrush oldBrush( liv->itemTextBackground() ); + QColorGroup mycg( cg ); + if ( liv->currentItem() == this ) { + liv->setItemTextBackground( cg.brush( QColorGroup::Highlight ) ); + mycg.setColor( QColorGroup::Text, cg.color( QColorGroup::HighlightedText ) ); + } + QIconViewItem::paintItem(p,mycg); + if ( liv->currentItem() == this ) + liv->setItemTextBackground( oldBrush ); + if ( liv->busyItem() == this ) { + static QPixmap* busypm=0; + if ( !busypm ) + busypm = new QPixmap(Resource::loadPixmap("launching")); + p->drawPixmap(x()+(width()-busypm->width())/2, y(),*busypm); + } + } + +protected: + AppLnk* app; +}; + + +LauncherItem::LauncherItem( QIconView *parent, AppLnk *applnk ) + : QIconViewItem( parent, applnk->name(), applnk->bigPixmap() ), + app(applnk) // Takes ownership +{ +} + +int LauncherItem::compare ( QIconViewItem * i ) const +{ + LauncherIconView* view = (LauncherIconView*)iconView(); + return view->compare(app,((LauncherItem *)i)->appLnk()); +} + +QStringList LauncherIconView::mimeTypes() const +{ + QStringList r; + QDictIterator it(mimes); + while (it.current()) { + r.append(it.currentKey()); + ++it; + } + r.sort(); + return r; +} + +void LauncherIconView::addItem(AppLnk* app, bool resort) +{ + addCatsAndMimes(app); + + if ( (tf.isEmpty() || tf.match(app->type()) >= 0) + && (cf == 0 || app->categories().contains(cf) + || cf == -1 && app->categories().count() == 0 ) ) + (void) new LauncherItem( this, app ); + else + hidden.append(app); + if ( resort ) + sort(); +} + +void LauncherIconView::updateCategoriesAndMimeTypes() +{ + mimes.clear(); + cats.clear(); + LauncherItem* item = (LauncherItem*)firstItem(); + while (item) { + addCatsAndMimes(item->appLnk()); + item = (LauncherItem*)item->nextItem(); + } + QListIterator it(hidden); + AppLnk* l; + while ((l=it.current())) { + addCatsAndMimes(l); + ++it; + } +} + +void LauncherIconView::hideOrShowItems(bool resort) +{ + hidden.setAutoDelete(FALSE); + QList links=hidden; + hidden.clear(); + hidden.setAutoDelete(TRUE); + LauncherItem* item = (LauncherItem*)firstItem(); + while (item) { + links.append(item->takeAppLnk()); + item = (LauncherItem*)item->nextItem(); + } + clear(); + QListIterator it(links); + AppLnk* l; + while ((l=it.current())) { + addItem(l,FALSE); + ++it; + } + if ( resort ) + sort(); +} + +bool LauncherIconView::removeLink(const QString& linkfile) +{ + LauncherItem* item = (LauncherItem*)firstItem(); + while (item) { + if ( item->appLnk()->linkFile() == linkfile ) { + delete item; + return TRUE; + } + item = (LauncherItem*)item->nextItem(); + } + QListIterator it(hidden); + AppLnk* l; + while ((l=it.current())) { + ++it; + if ( l->linkFile() == linkfile ) { + hidden.removeRef(l); + return TRUE; + } + } + return FALSE; +} + +LauncherView::LauncherView( QWidget* parent, const char* name, WFlags fl ) + : QVBox( parent, name, fl ) +{ + icons = new LauncherIconView( this ); + setFocusProxy(icons); + QPEApplication::setStylusOperation( icons->viewport(), QPEApplication::RightOnHold ); + + int dw = QApplication::desktop()->width(); + icons->setItemsMovable( FALSE ); + icons->setAutoArrange( TRUE ); + icons->setSorting( TRUE ); + icons->setGridX( (dw-13-style().scrollBarExtent().width())/3 ); // tweaked for 8pt+dw=176 and 10pt+dw=240 + icons->setGridY( fontMetrics().height()*2+24 ); + icons->setFrameStyle( QFrame::NoFrame ); + icons->setSpacing( 4 ); + icons->setMargin( 0 ); + icons->setSelectionMode( QIconView::Multi ); + icons->setBackgroundMode( PaletteBase ); + + connect( icons, SIGNAL(mouseButtonClicked(int, QIconViewItem *, const QPoint&)), + SLOT(itemClicked(int, QIconViewItem *)) ); + connect( icons, SIGNAL(selectionChanged()), + SLOT(selectionChanged()) ); + connect( icons, SIGNAL(returnPressed(QIconViewItem *)), + SLOT(returnPressed(QIconViewItem *)) ); + connect( icons, SIGNAL(mouseButtonPressed(int, QIconViewItem *, const QPoint&)), + SLOT(itemPressed(int, QIconViewItem *)) ); + + tools = 0; +} + +LauncherView::~LauncherView() +{ +} + +void LauncherView::setToolsEnabled(bool y) +{ + if ( !y != !tools ) { + if ( y ) { + tools = new QHBox(this); + + // Type filter + typemb = new MenuButton(tools); + typemb->setLabel(tr("Type: %1")); + + // Category filter + catmb = new CategorySelect(tools); + + updateTools(); + tools->show(); + } else { + delete tools; + tools = 0; + } + } +} + +void LauncherView::updateTools() +{ + disconnect( typemb, SIGNAL(selected(const QString&)), + this, SLOT(showType(const QString&)) ); + disconnect( catmb, SIGNAL(signalSelected(int)), + this, SLOT(showCategory(int)) ); + + icons->updateCategoriesAndMimeTypes(); + + QString prev; + + // Type filter + QStringList types; + types << tr("All"); + types << "--"; + types += icons->mimeTypes(); + prev = typemb->currentText(); + typemb->clear(); + typemb->insertItems(types); + typemb->select(prev); + + Categories cats( 0 ); + cats.load( categoryFileName() ); + QArray vl( 0 ); + catmb->setCategories( vl, "Document View", tr("Document View") ); + catmb->setRemoveCategoryEdit( TRUE ); + catmb->setAllCategories( TRUE ); + + connect(typemb, SIGNAL(selected(const QString&)), this, SLOT(showType(const QString&))); + connect(catmb, SIGNAL(signalSelected(int)), this, SLOT(showCategory(int))); +} + +void LauncherView::sortBy(int s) +{ + icons->setSortMethod((LauncherIconView::SortMethod)s); +} + +void LauncherView::showType(const QString& t) +{ + if ( t == tr("All") ) { + icons->setTypeFilter("",TRUE); + } else { + icons->setTypeFilter(t+"/*",TRUE); + } +} + +void LauncherView::showCategory( int c ) +{ + icons->setCategoryFilter( c, TRUE ); +} + +void LauncherView::resizeEvent(QResizeEvent *e) +{ + QVBox::resizeEvent( e ); + if ( e->size().width() != e->oldSize().width() ) + sort(); +} + +void LauncherView::populate( AppLnkSet *folder, const QString& typefilter ) +{ + icons->clear(); + internalPopulate( folder, typefilter ); +} + +void LauncherView::selectionChanged() +{ + QIconViewItem* item = icons->currentItem(); + if ( item && item->isSelected() ) { + AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); + if ( icons->inKeyEvent() ) // not for mouse press + emit clicked( appLnk ); + item->setSelected(FALSE); + } +} + +void LauncherView::returnPressed( QIconViewItem *item ) +{ + if ( item ) { + AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); + emit clicked( appLnk ); + } +} + +void LauncherView::itemClicked( int btn, QIconViewItem *item ) +{ + if ( item ) { + AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); + if ( btn == LeftButton ) { + // Make sure it's the item we execute that gets highlighted + icons->setCurrentItem( item ); + emit clicked( appLnk ); + } + item->setSelected(FALSE); + } +} + +void LauncherView::itemPressed( int btn, QIconViewItem *item ) +{ + if ( item ) { + AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); + if ( btn == RightButton ) + emit rightPressed( appLnk ); +/* + else if ( btn == LeftButton ) + emit clicked( appLnk ); +*/ + item->setSelected(FALSE); + } +} + +void LauncherView::internalPopulate( AppLnkSet *folder, const QString& typefilter ) +{ + QListIterator it( folder->children() ); + icons->setTypeFilter(typefilter,FALSE); + + while ( it.current() ) { + icons->addItem(*it,FALSE); + ++it; + } + + icons->sort(); +} + +bool LauncherView::removeLink(const QString& linkfile) +{ + return icons->removeLink(linkfile); +} + +void LauncherView::sort() +{ + icons->sort(); +} + +void LauncherView::addItem(AppLnk* app, bool resort) +{ + icons->addItem(app,resort); +} + +void LauncherView::setFileSystems(const QList &) +{ + // ### does nothing now... +} diff --git a/core/launcher/launcherview.h b/core/launcher/launcherview.h new file mode 100644 index 0000000..3aaef7e --- a/dev/null +++ b/core/launcher/launcherview.h @@ -0,0 +1,81 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef LAUNCHERVIEW_H +#define LAUNCHERVIEW_H + +#include + +#include + +class AppLnk; +class AppLnkSet; +class CategorySelect; +class LauncherIconView; +class QIconView; +class QIconViewItem; +class MenuButton; + +class LauncherView : public QVBox +{ + Q_OBJECT + +public: + LauncherView( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~LauncherView(); + + bool removeLink(const QString& linkfile); + void addItem(AppLnk* app, bool resort=TRUE); + void sort(); + + void setFileSystems(const QList &); + void setToolsEnabled(bool); + void updateTools(); + + void setBusy(bool); + +public slots: + void populate( AppLnkSet *folder, const QString& categoryfilter ); + +signals: + void clicked( const AppLnk * ); + void rightPressed( AppLnk * ); + +protected slots: + void selectionChanged(); + void returnPressed( QIconViewItem *item ); + void itemClicked( int, QIconViewItem * ); + void itemPressed( int, QIconViewItem * ); + void sortBy(int); + void showType(const QString&); + void showCategory( int ); + void resizeEvent(QResizeEvent *); + +protected: + void internalPopulate( AppLnkSet *, const QString& categoryfilter ); + +private: + static bool bsy; + QWidget* tools; + LauncherIconView* icons; + MenuButton *typemb; + CategorySelect *catmb; +}; + +#endif // LAUNCHERVIEW_H diff --git a/core/launcher/main.cpp b/core/launcher/main.cpp new file mode 100644 index 0000000..024f9cc --- a/dev/null +++ b/core/launcher/main.cpp @@ -0,0 +1,276 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "desktop.h" +#include "taskbar.h" +#include "stabmon.h" + +#include +#include +#include +#ifdef QT_QWS_CUSTOM +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(QT_QWS_CASSIOPEIA) || defined(QT_QWS_IPAQ) || defined(QT_QWS_EBX) +#include "../calibrate/calibrate.h" +#endif + +#ifdef QT_QWS_LOGIN +#include "../login/qdmdialogimpl.h" +#endif + +#ifdef QT_QWS_CASSIOPEIA +static void ignoreMessage( QtMsgType, const char * ) +{ +} +#include +#include +#include +#include +#include +#include + +void initCassiopeia() +{ + // MIPSEL-specific init - make sure /proc exists for shm +/* + if ( mount("/dev/ram0", "/", "ext2", MS_REMOUNT | MS_MGC_VAL, 0 ) ) { + perror("Remounting - / read/write"); + } +*/ + if ( mount("none", "/tmp", "ramfs", 0, 0 ) ) { + perror("mounting ramfs /tmp"); + } else { + fprintf( stderr, "mounted /tmp\n" ); + } + if ( mount("none", "/home", "ramfs", 0, 0 ) ) { + perror("mounting ramfs /home"); + } else { + fprintf( stderr, "mounted /home\n" ); + } + if ( mount("none","/proc","proc",0,0) ) { + perror("Mounting - /proc"); + } else { + fprintf( stderr, "mounted /proc\n" ); + } + if ( mount("none","/mnt","shm",0,0) ) { + perror("Mounting - shm"); + } + setenv( "QTDIR", "/", 1 ); + setenv( "QPEDIR", "/", 1 ); + setenv( "HOME", "/home", 1 ); + mkdir( "/home/Documents", 0755 ); + + // set a reasonable starting date + QDateTime dt( QDate( 2001, 3, 15 ) ); + QDateTime now = QDateTime::currentDateTime(); + int change = now.secsTo( dt ); + + time_t t = ::time(0); + t += change; + stime(&t); + + qInstallMsgHandler(ignoreMessage); +} +#endif + +#ifdef QPE_OWNAPM +#include +#include +#include +#include +#include +#include +#include + +static void disableAPM() +{ + + int fd, cur_val, ret; + char *device = "/dev/apm_bios"; + + fd = open (device, O_WRONLY); + + if (fd == -1) { + perror(device); + return; + } + + cur_val = ioctl(fd, APM_IOCGEVTSRC, 0); + if (cur_val == -1) { + perror("ioctl"); + exit(errno); + } + + ret = ioctl(fd, APM_IOCSEVTSRC, cur_val & ~APM_EVT_POWER_BUTTON); + if (ret == -1) { + perror("ioctl"); + return; + } + close(fd); +} + +static void initAPM() +{ + // So that we have to do it ourself, but better. + disableAPM(); +} +#endif + +#ifdef QT_DEMO_SINGLE_FLOPPY +#include + +void initFloppy() +{ + mount("none","/proc","proc",0,0); + setenv( "QTDIR", "/", 0 ); + setenv( "HOME", "/root", 0 ); + setenv( "QWS_SIZE", "240x320", 0 ); +} +#endif + + +void initEnvironment() +{ + Config config("locale"); + config.setGroup( "Location" ); + QString tz = config.readEntry( "Timezone", getenv("TZ") ); + + // if not timezone set, pick New York + if (tz.isNull()) + tz = "America/New_York"; + + setenv( "TZ", tz, 1 ); + config.writeEntry( "Timezone", tz); + + config.setGroup( "Language" ); + QString lang = config.readEntry( "Language", getenv("LANG") ); + if ( !lang.isNull() ) + setenv( "LANG", lang, 1 ); +} + +static void initBacklight() +{ + QCopEnvelope e("QPE/System", "setBacklight(int)" ); + e << -3; // Forced on +} + + + +int initApplication( int argc, char ** argv ) +{ +#ifdef QT_QWS_CASSIOPEIA + initCassiopeia(); +#endif + +#ifdef QPE_OWNAPM + initAPM(); +#endif + +#ifdef QT_DEMO_SINGLE_FLOPPY + initFloppy(); +#endif + + initEnvironment(); + +#if !defined(QT_QWS_CASSIOPEIA) && !defined(QT_QWS_IPAQ) && !defined(QT_QWS_EBX) + setenv( "QWS_SIZE", "240x320", 0 ); +#endif + + //Don't flicker at startup: + QWSServer::setDesktopBackground( QImage() ); + DesktopApplication a( argc, argv, QApplication::GuiServer ); + + initBacklight(); + + AlarmServer::initialize(); + +#if defined(QT_QWS_LOGIN) + for( int i=0; iexec(); + delete cal; + } +#endif + + d->show(); + + int rv = a.exec(); + + delete d; + + return rv; +} + +int main( int argc, char ** argv ) +{ +#ifndef SINGLE_APP + signal( SIGCHLD, SIG_IGN ); +#endif + + int retVal = initApplication( argc, argv ); + +#ifndef SINGLE_APP + // Kill them. Kill them all. + setpgid( getpid(), getppid() ); + killpg( getpid(), SIGTERM ); + sleep( 1 ); + killpg( getpid(), SIGKILL ); +#endif + + return retVal; +} + diff --git a/core/launcher/mrulist.cpp b/core/launcher/mrulist.cpp new file mode 100644 index 0000000..4daf7d2 --- a/dev/null +++ b/core/launcher/mrulist.cpp @@ -0,0 +1,199 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "mrulist.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +QList *MRUList::MRUListWidgets = NULL; +QList *MRUList::task = NULL; + + +MRUList::MRUList( QWidget *parent ) + : QFrame( parent ), selected(-1), oldsel(-1) +{ + setBackgroundMode( PaletteButton ); + if (!MRUListWidgets) + MRUListWidgets = new QList; + if (!task) + task = new QList; + MRUListWidgets->append( this ); +} + + +MRUList::~MRUList() +{ + if (MRUListWidgets) + MRUListWidgets->remove( this ); + if (task) + task->setAutoDelete( TRUE ); +} + + +QSize MRUList::sizeHint() const +{ + return QSize( frameWidth(), 16 ); +} + + +void MRUList::addTask( const AppLnk *appLnk ) +{ + if ( !appLnk ) + return; + unsigned int i = 0; + + if ( !task ) + return; + + for ( ; i < task->count(); i++ ) { + AppLnk *t = task->at(i); + if ( t->exec() == appLnk->exec() ) { + if (i != 0) { + task->remove(); + task->prepend( t ); + } + for (unsigned i = 0; i < MRUListWidgets->count(); i++ ) + MRUListWidgets->at(i)->update(); + return; + } + } + + AppLnk *t = new AppLnk( *appLnk ); + // DocLnks have an overloaded virtual function exec() + t->setExec( appLnk->exec() ); + task->prepend( t ); + + if ( task->count() > 6 ) { + t = task->last(); + task->remove(); + Global::terminate(t); + delete t; + } + + for (unsigned i = 0; i < MRUListWidgets->count(); i++ ) + MRUListWidgets->at(i)->update(); +} + +bool MRUList::quitOldApps() +{ + QStringList appsstarted; + QStringList appsrunning; + for ( int i=task->count()-1; i>=0; --i ) { + AppLnk *t = task->at(i); + appsstarted.append(t->exec()); + } + + const QList &list = qwsServer->clientWindows(); + QWSWindow* w; + for (QListIterator it(list); (w=it.current()); ++it) { + QString app = w->client()->identity(); + if ( appsstarted.contains(app) && !appsrunning.contains(app) ) + appsrunning.append(app); + } + + if ( appsrunning.count() > 1 ) { + QStringList::ConstIterator it = appsrunning.begin(); + ++it; // top stays running! + for (; it != appsrunning.end(); it++) { + for ( int i=task->count()-1; i>=0; --i ) { + AppLnk *t = task->at(i); + if ( t->exec() == *it ) + Global::terminate(t); + } + } + return TRUE; + } else { + return FALSE; + } +} + + +void MRUList::mousePressEvent(QMouseEvent *e) +{ + selected = 0; + int x=0; + QListIterator it( *task ); + for ( ; it.current(); ++it,++selected,x+=15 ) { + if ( x + 15 <= width() ) { + if ( e->x() >= x && e->x() < x+15 ) { + if ( selected < (int)task->count() ) { + repaint(FALSE); + return; + } + } + } else { + break; + } + } + selected = -1; + repaint( FALSE ); +} + + +void MRUList::mouseReleaseEvent(QMouseEvent *) +{ + if ( selected >= 0 ) { + if ( parentWidget() ) + if ( parentWidget()->isA( "QPopupMenu" ) ) + parentWidget()->hide(); + Global::execute( task->at(selected)->exec() ); + selected = -1; + oldsel = -1; + update(); + } +} + + +void MRUList::paintEvent( QPaintEvent * ) +{ + QPainter p( this ); + AppLnk *t; + int x = 0; + int y = (height() - 14) / 2; + int i = 0; + + p.fillRect( 0, 0, width(), height(), colorGroup().background() ); + + if ( task ) { + QListIterator it( *task ); + for ( ; it.current(); i++, ++it ) { + if ( x + 15 <= width() ) { + t = it.current(); + if ( (int)i == selected ) + p.fillRect( x, y, 15, t->pixmap().height()+1, colorGroup().highlight() ); + else if ( (int)i == oldsel ) + p.eraseRect( x, y, 15, t->pixmap().height()+1 ); + p.drawPixmap( x, y, t->pixmap() ); + x += 15; + } + } + } +} + diff --git a/core/launcher/mrulist.h b/core/launcher/mrulist.h new file mode 100644 index 0000000..141a09b --- a/dev/null +++ b/core/launcher/mrulist.h @@ -0,0 +1,55 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __MRU_LIST_H__ +#define __MRU_LIST_H__ + + +#include + +#include +#include +#include + + +class MRUList : public QFrame +{ +public: + MRUList( QWidget *parent ); + ~MRUList(); + virtual QSize sizeHint() const; + static void addTask( const AppLnk *appLnk ); + bool quitOldApps(); + +protected: + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void paintEvent( QPaintEvent *event ); + +private: + static QList *MRUListWidgets; + static QList *task; + int selected; + int oldsel; +}; + + +#endif // __MRU_LIST_H__ + diff --git a/core/launcher/obexinterface.h b/core/launcher/obexinterface.h new file mode 100644 index 0000000..a73fde6 --- a/dev/null +++ b/core/launcher/obexinterface.h @@ -0,0 +1,40 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef OBEXINTERFACE_H +#define OBEXINTERFACE_H + +#include + +#ifndef QT_NO_COMPONENT +// ### regenerate!!!!!! +// {6CA35D0B-C637-4865-A667-7D4CD8A70407} +# ifndef IID_ObexInterface +# define IID_ObexInterface QUuid( 0x6ca35d0b, 0xc637, 0x4865, 0xa6, 0x67, 0x7d, 0x4c, 0xd8, 0xa7, 0x04, 0x07) +# endif +#endif + +class QObject; + +struct ObexInterface : public QUnknownInterface +{ +}; + +#endif diff --git a/core/launcher/packageslave.cpp b/core/launcher/packageslave.cpp new file mode 100644 index 0000000..4f149a5 --- a/dev/null +++ b/core/launcher/packageslave.cpp @@ -0,0 +1,97 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "packageslave.h" + +#include +#include + +#include +#include + +#include + +PackageSlave::PackageSlave( QObject *parent, char* name ) + : QObject( parent, name ), packageChannel( 0 ) +{ + // setup qcop channel + packageChannel = new QCopChannel( "QPE/Package", this ); + connect( packageChannel, SIGNAL( received(const QCString &, const QByteArray &) ), + this, SLOT( qcopMessage( const QCString &, const QByteArray &) ) ); +} + +void PackageSlave::qcopMessage( const QCString &msg, const QByteArray &data ) +{ + QDataStream stream( data, IO_ReadOnly ); + + if ( msg == "installPackage(QString)" ) { + QString file; + stream >> file; + installPackage( file ); + } + else if ( msg == "removePackage(QString)" ) { + QString file; + stream >> file; + removePackage( file ); + } +} + +void PackageSlave::installPackage( const QString &package ) +{ + Process proc( QStringList() << "ipkg" << "install" << package ); + + sendReply( "installStarted(QString)", package ); + + QString output; + if ( proc.exec( "", output ) ) { + sendReply( "installDone(QString)", package ); + } + else { + sendReply( "installFailed(QString)", package ); + } + QCopEnvelope e("QPE/System", "linkChanged(QString)"); + QString lf = QString::null; + e << lf; + unlink( package ); +} + +void PackageSlave::removePackage( const QString &package ) +{ + Process proc( QStringList() << "ipkg" << "remove" << package ); + + sendReply( "removeStarted(QString)", package ); + + QString output; + if ( proc.exec( "", output ) ) { + sendReply( "removeDone(QString)", package ); + } + else { + sendReply( "removeFailed(QString)", package ); + } + QCopEnvelope e("QPE/System", "linkChanged(QString)"); + QString lf = QString::null; + e << lf; +} + +void PackageSlave::sendReply( const QCString& msg, const QString& arg ) +{ + QCopEnvelope e( "QPE/Desktop", msg ); + e << arg; +} diff --git a/core/launcher/packageslave.h b/core/launcher/packageslave.h new file mode 100644 index 0000000..036abed --- a/dev/null +++ b/core/launcher/packageslave.h @@ -0,0 +1,52 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __packageslave_h__ +#define __packageslave_h__ + +#include + +class QCopChannel; + +class PackageSlave : public QObject +{ + Q_OBJECT + +public: + PackageSlave( QObject *parent, char* name = 0 ); + +protected: + void installPackage( const QString &package ); + void removePackage( const QString &package ); + +protected slots: + void qcopMessage( const QCString &msg, const QByteArray &data ); + +private: + void sendReply( const QCString& msg, const QString& arg ); + +private: + QCopChannel *packageChannel; +}; + + +#endif // __QUICK_LAUNCHER_H__ + + diff --git a/core/launcher/qcopbridge.cpp b/core/launcher/qcopbridge.cpp new file mode 100644 index 0000000..c78e827 --- a/dev/null +++ b/core/launcher/qcopbridge.cpp @@ -0,0 +1,416 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qcopbridge.h" +#include "transferserver.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define _XOPEN_SOURCE +#include +#include +#include + +#if defined(_OS_LINUX_) +#include +#endif + +//#define INSECURE + +const int block_size = 51200; + +QCopBridge::QCopBridge( Q_UINT16 port, QObject *parent = 0, + const char* name = 0) + : QServerSocket( port, 1, parent, name ), + desktopChannel( 0 ), + cardChannel( 0 ) +{ + if ( !ok() ) + qWarning( "Failed to bind to port %d", port ); + else { + desktopChannel = new QCopChannel( "QPE/Desktop", this ); + connect( desktopChannel, SIGNAL(received(const QCString &, const QByteArray &)), + this, SLOT(desktopMessage( const QCString &, const QByteArray &)) ); + cardChannel = new QCopChannel( "QPE/Card", this ); + connect( cardChannel, SIGNAL(received(const QCString &, const QByteArray &)), + this, SLOT(desktopMessage( const QCString &, const QByteArray &)) ); + } + sendSync = FALSE; +} + +QCopBridge::~QCopBridge() +{ + delete desktopChannel; +} + +void QCopBridge::newConnection( int socket ) +{ + QCopBridgePI *pi = new QCopBridgePI( socket, this ); + openConnections.append( pi ); + connect ( pi, SIGNAL( connectionClosed( QCopBridgePI *) ), this, SLOT( connectionClosed( QCopBridgePI *) ) ); + QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::DisableSuspend; + + if ( sendSync ) { + pi ->startSync(); + sendSync = FALSE; + } +} + +void QCopBridge::connectionClosed( QCopBridgePI *pi ) +{ + openConnections.remove( pi ); + if ( openConnections.count() == 0 ) { + QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable; + } +} + +void QCopBridge::closeOpenConnections() +{ + QCopBridgePI *pi; + for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) + pi->close(); +} + + +void QCopBridge::desktopMessage( const QCString &command, const QByteArray &args ) +{ + command.stripWhiteSpace(); + + int paren = command.find( "(" ); + if ( paren <= 0 ) { + qDebug("DesktopMessage: bad qcop syntax"); + return; + } + + QString params = command.mid( paren + 1 ); + if ( params[params.length()-1] != ')' ) { + qDebug("DesktopMessage: bad qcop syntax"); + return; + } + + params.truncate( params.length()-1 ); + + QStringList paramList = QStringList::split( ",", params ); + QString data; + if ( paramList.count() ) { + QDataStream stream( args, IO_ReadOnly ); + for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) { + QString str; + if ( *it == "QString" ) { + stream >> str; + } else if ( *it == "QCString" ) { + QCString cstr; + stream >> cstr; + str = QString::fromLocal8Bit( cstr ); + } else if ( *it == "int" ) { + int i; + stream >> i; + str = QString::number( i ); + } else if ( *it == "bool" ) { + int i; + stream >> i; + str = QString::number( i ); + } else { + qDebug(" cannot route the argument type %s throught the qcop bridge", (*it).latin1() ); + return; + } + str.replace( QRegExp("&"), "&" ); + str.replace( QRegExp(" "), "&0x20;" ); + str.replace( QRegExp("\n"), "&0x0d;" ); + str.replace( QRegExp("\r"), "&0x0a;" ); + data += " " + str; + } + } + QString sendCommand = QString(command.data()) + data; + // send the command to all open connections + if ( command == "startSync()" ) { + // we need to buffer it a bit + sendSync = TRUE; + startTimer( 20000 ); + } + + QCopBridgePI *pi; + for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) { + pi->sendDesktopMessage( sendCommand ); + } +} + +void QCopBridge::timerEvent( QTimerEvent * ) +{ + sendSync = FALSE; + killTimers(); +} + + +QCopBridgePI::QCopBridgePI( int socket, QObject *parent = 0, const char* name = 0 ) + : QSocket( parent, name ) +{ + setSocket( socket ); + + peerport = peerPort(); + peeraddress = peerAddress(); + +#ifndef INSECURE + if ( !accessAuthorized(peeraddress) ) { + state = Forbidden; + startTimer( 0 ); + } else +#endif + { + state = Connected; + sendSync = FALSE; + connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); + connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); + + send( "220 Qtopia QCop bridge ready!" ); + state = Wait_USER; + + // idle timer to close connections when not used anymore + startTimer( 60000 ); + connected = TRUE; + } +} + + +QCopBridgePI::~QCopBridgePI() +{ + +} + +void QCopBridgePI::connectionClosed() +{ + emit connectionClosed( this ); + // qDebug( "Debug: Connection closed" ); + delete this; +} + +void QCopBridgePI::sendDesktopMessage( const QString &msg ) +{ + QString str = "CALL QPE/Desktop " + msg; + send ( str ); +} + + +void QCopBridgePI::send( const QString& msg ) +{ + QTextStream os( this ); + os << msg << endl; + //qDebug( "sending qcop message: %s", msg.latin1() ); +} + +void QCopBridgePI::read() +{ + while ( canReadLine() ) + process( readLine().stripWhiteSpace() ); +} + +bool QCopBridgePI::checkUser( const QString& user ) +{ + if ( user.isEmpty() ) return FALSE; + + struct passwd *pw; + pw = getpwuid( geteuid() ); + QString euser = QString::fromLocal8Bit( pw->pw_name ); + return user == euser; +} + +bool QCopBridgePI::checkPassword( const QString& password ) +{ + // ### HACK for testing on local host + return true; + + /* + struct passwd *pw = 0; + struct spwd *spw = 0; + + pw = getpwuid( geteuid() ); + spw = getspnam( pw->pw_name ); + + QString cpwd = QString::fromLocal8Bit( pw->pw_passwd ); + if ( cpwd == "x" && spw ) + cpwd = QString::fromLocal8Bit( spw->sp_pwdp ); + + QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) ); + return cpwd == cpassword; +*/ +} + +void QCopBridgePI::process( const QString& message ) +{ + //qDebug( "Command: %s", message.latin1() ); + + // split message using "," as separator + QStringList msg = QStringList::split( " ", message ); + if ( msg.isEmpty() ) return; + + // command token + QString cmd = msg[0].upper(); + + // argument token + QString arg; + if ( msg.count() >= 2 ) + arg = msg[1]; + + // we always respond to QUIT, regardless of state + if ( cmd == "QUIT" ) { + send( "211 Have a nice day!" ); + delete this; + return; + } + + // connected to client + if ( Connected == state ) + return; + + // waiting for user name + if ( Wait_USER == state ) { + + if ( cmd != "USER" || msg.count() < 2 || !checkUser( arg ) ) { + send( "530 Please login with USER and PASS" ); + return; + } + send( "331 User name ok, need password" ); + state = Wait_PASS; + return; + } + + // waiting for password + if ( Wait_PASS == state ) { + + if ( cmd != "PASS" || !checkPassword( arg ) ) { + //if ( cmd != "PASS" || msg.count() < 2 || !checkPassword( arg ) ) { + send( "530 Please login with USER and PASS" ); + return; + } + send( "230 User logged in, proceed" ); + state = Ready; + if ( sendSync ) { + sendDesktopMessage( "startSync()" ); + sendSync = FALSE; + } + return; + } + + // noop (NOOP) + else if ( cmd == "NOOP" ) { + connected = TRUE; + send( "200 Command okay" ); + } + + // call (CALL) + else if ( cmd == "CALL" ) { + + // example: call QPE/System execute(QString) addressbook + + if ( msg.count() < 3 ) { + send( "500 Syntax error, command unrecognized" ); + } + else { + + QString channel = msg[1]; + QString command = msg[2]; + + command.stripWhiteSpace(); + + int paren = command.find( "(" ); + if ( paren <= 0 ) { + send( "500 Syntax error, command unrecognized" ); + return; + } + + QString params = command.mid( paren + 1 ); + if ( params[params.length()-1] != ')' ) { + send( "500 Syntax error, command unrecognized" ); + return; + } + + params.truncate( params.length()-1 ); + QByteArray buffer; + QDataStream ds( buffer, IO_WriteOnly ); + + int msgId = 3; + + QStringList paramList = QStringList::split( ",", params ); + if ( paramList.count() > msg.count() - 3 ) { + send( "500 Syntax error, command unrecognized" ); + return; + } + + for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) { + + QString arg = msg[msgId]; + arg.replace( QRegExp("&0x20;"), " " ); + arg.replace( QRegExp("&"), "&" ); + arg.replace( QRegExp("&0x0d;"), "\n" ); + arg.replace( QRegExp("&0x0a;"), "\r" ); + if ( *it == "QString" ) + ds << arg; + else if ( *it == "QCString" ) + ds << arg.local8Bit(); + else if ( *it == "int" ) + ds << arg.toInt(); + else if ( *it == "bool" ) + ds << arg.toInt(); + else { + send( "500 Syntax error, command unrecognized" ); + return; + } + msgId++; + } + + if ( !QCopChannel::isRegistered( channel.latin1() ) ) { + // send message back about it + QString answer = "599 ChannelNotRegistered " + channel; + send( answer ); + return; + } + + if ( paramList.count() ) + QCopChannel::send( channel.latin1(), command.latin1(), buffer ); + else + QCopChannel::send( channel.latin1(), command.latin1() ); + + send( "200 Command okay" ); + } + } + // not implemented + else + send( "502 Command not implemented" ); +} + + + +void QCopBridgePI::timerEvent( QTimerEvent * ) +{ + if ( connected ) + connected = FALSE; + else + connectionClosed(); +} diff --git a/core/launcher/qcopbridge.h b/core/launcher/qcopbridge.h new file mode 100644 index 0000000..114b3ee --- a/dev/null +++ b/core/launcher/qcopbridge.h @@ -0,0 +1,95 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __qcopbridge_h__ +#define __qcopbridge_h__ + +#include +#include +#include +#include +#include + +class QFileInfo; +class QCopBridgePI; +class QCopChannel; + +class QCopBridge : public QServerSocket +{ + Q_OBJECT + +public: + QCopBridge( Q_UINT16 port, QObject *parent = 0, const char* name = 0 ); + virtual ~QCopBridge(); + + void newConnection( int socket ); + void closeOpenConnections(); + +public slots: + void connectionClosed( QCopBridgePI *pi ); + void desktopMessage( const QCString &call, const QByteArray & ); + +protected: + void timerEvent( QTimerEvent * ); + +private: + QCopChannel *desktopChannel; + QCopChannel *cardChannel; + QList openConnections; + bool sendSync; +}; + + +class QCopBridgePI : public QSocket +{ + Q_OBJECT + + enum State { Connected, Wait_USER, Wait_PASS, Ready, Forbidden }; + +public: + QCopBridgePI( int socket, QObject *parent = 0, const char* name = 0 ); + virtual ~QCopBridgePI(); + + void sendDesktopMessage( const QString &msg ); + void startSync() { sendSync = TRUE; } + +signals: + void connectionClosed( QCopBridgePI *); + +protected slots: + void read(); + void send( const QString& msg ); + void process( const QString& command ); + void connectionClosed(); + +protected: + bool checkUser( const QString& user ); + bool checkPassword( const QString& pw ); + + void timerEvent( QTimerEvent *e ); + +private: + State state; + Q_UINT16 peerport; + QHostAddress peeraddress; + bool connected; + bool sendSync; +}; + +#endif diff --git a/core/launcher/qpe-taskbar.control b/core/launcher/qpe-taskbar.control new file mode 100644 index 0000000..f78f136 --- a/dev/null +++ b/core/launcher/qpe-taskbar.control @@ -0,0 +1,9 @@ +Files: bin/qpe apps/Settings/Calibrate.desktop +Priority: required +Section: qpe/system +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qt-embedded (>=$QTE_VERSION) +Description: Launcher for QPE + The "finder" or "explorer", or whatever you want to call it. diff --git a/core/launcher/quicklauncher.cpp b/core/launcher/quicklauncher.cpp new file mode 100644 index 0000000..925b3b5 --- a/dev/null +++ b/core/launcher/quicklauncher.cpp @@ -0,0 +1,49 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include +#include +#include +#include +#include +#include "quicklauncher.h" + + +void QuickLauncher::addLauncherButton( AppLnk *appLnk ) +{ + QPushButton *pb = new QPushButton( this ); + // It's no a QObject anymore + //pb->connect( pb, SIGNAL( clicked( ) ), appLnk, SLOT( execute() ) ); + pb->setPixmap( appLnk->pixmap() ); + pb->setFocusPolicy( QWidget::NoFocus ); + pb->setFlat( TRUE ); + pb->setFixedSize( 18, 18 ); +} + + +QuickLauncher::QuickLauncher( QWidget *parent ) : QHBox( parent ) +{ +// Example usage to add icons to the quick launcher area +// addLauncherButton( "filebrowser_icon", "filebrowser" ); +// addLauncherButton( "textedit_icon", "textedit" ); +// addLauncherButton( "help_icon", "helpbrowser" ); +} + + diff --git a/core/launcher/quicklauncher.h b/core/launcher/quicklauncher.h new file mode 100644 index 0000000..92c6c66 --- a/dev/null +++ b/core/launcher/quicklauncher.h @@ -0,0 +1,40 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __QUICK_LAUNCHER_H__ +#define __QUICK_LAUNCHER_H__ + + +#include + +class AppLnk; + + +class QuickLauncher : public QHBox { + Q_OBJECT +public: + QuickLauncher( QWidget *parent ); + void addLauncherButton( AppLnk * ); +}; + + +#endif // __QUICK_LAUNCHER_H__ + + diff --git a/core/launcher/shutdown.ui b/core/launcher/shutdown.ui new file mode 100644 index 0000000..0023427 --- a/dev/null +++ b/core/launcher/shutdown.ui @@ -0,0 +1,1323 @@ + +Shutdown + + QWidget + + name + Form1 + + + geometry + + 0 + 0 + 437 + 465 + + + + caption + Shut down... + + + layoutMargin + + + layoutSpacing + + + + margin + 6 + + + spacing + 3 + + + QButtonGroup + + name + ButtonGroup1 + + + title + Terminate + + + layoutMargin + + + layoutSpacing + + + + margin + 7 + + + spacing + 3 + + + QPushButton + + name + quit + + + sizePolicy + + 3 + 0 + + + + palette + + + + 0 + 0 + 0 + + + 236 + 236 + 179 + + + 255 + 255 + 255 + + + 245 + 245 + 217 + + + 118 + 118 + 89 + + + 157 + 157 + 119 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + 128 + 128 + 128 + + + 236 + 236 + 179 + + + 255 + 255 + 255 + + + 255 + 255 + 209 + + + 118 + 118 + 89 + + + 157 + 157 + 119 + + + 128 + 128 + 128 + + + 255 + 255 + 255 + + + 128 + 128 + 128 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + 0 + 0 + 0 + + + 236 + 236 + 179 + + + 255 + 255 + 255 + + + 255 + 255 + 209 + + + 118 + 118 + 89 + + + 157 + 157 + 119 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + + text + Terminate Server + + + buttonGroupId + 4 + + + + QPushButton + + name + reboot + + + sizePolicy + + 3 + 0 + + + + palette + + + + 0 + 0 + 0 + + + 236 + 183 + 181 + + + 255 + 255 + 255 + + + 245 + 219 + 218 + + + 118 + 92 + 91 + + + 157 + 122 + 121 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + 128 + 128 + 128 + + + 236 + 183 + 181 + + + 255 + 255 + 255 + + + 255 + 213 + 212 + + + 118 + 92 + 91 + + + 157 + 122 + 121 + + + 128 + 128 + 128 + + + 255 + 255 + 255 + + + 128 + 128 + 128 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + 0 + 0 + 0 + + + 236 + 183 + 181 + + + 255 + 255 + 255 + + + 255 + 213 + 212 + + + 118 + 92 + 91 + + + 157 + 122 + 121 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + + text + Reboot + + + buttonGroupId + 2 + + + + QPushButton + + name + restart + + + palette + + + + 0 + 0 + 0 + + + 236 + 236 + 179 + + + 255 + 255 + 255 + + + 245 + 245 + 217 + + + 118 + 118 + 89 + + + 157 + 157 + 119 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + 128 + 128 + 128 + + + 236 + 236 + 179 + + + 255 + 255 + 255 + + + 255 + 255 + 209 + + + 118 + 118 + 89 + + + 157 + 157 + 119 + + + 128 + 128 + 128 + + + 255 + 255 + 255 + + + 128 + 128 + 128 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + 0 + 0 + 0 + + + 236 + 236 + 179 + + + 255 + 255 + 255 + + + 255 + 255 + 209 + + + 118 + 118 + 89 + + + 157 + 157 + 119 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + + text + Restart Server + + + buttonGroupId + 3 + + + + QPushButton + + name + shutdown + + + palette + + + + 0 + 0 + 0 + + + 236 + 183 + 181 + + + 255 + 255 + 255 + + + 245 + 219 + 218 + + + 118 + 92 + 91 + + + 157 + 122 + 121 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + 128 + 128 + 128 + + + 236 + 183 + 181 + + + 255 + 255 + 255 + + + 255 + 213 + 212 + + + 118 + 92 + 91 + + + 157 + 122 + 121 + + + 128 + 128 + 128 + + + 255 + 255 + 255 + + + 128 + 128 + 128 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + 0 + 0 + 0 + + + 236 + 183 + 181 + + + 255 + 255 + 255 + + + 255 + 213 + 212 + + + 118 + 92 + 91 + + + 157 + 122 + 121 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 222 + 222 + 222 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + + text + Shutdown + + + buttonGroupId + 1 + + + + + + QLabel + + name + info + + + text + <p> +These termination options are provided primarily for use while developing and testing the Qtopia system. In a normal environment, these concepts are unnecessary. + + + + QProgressBar + + name + progressBar + + + frameShape + Panel + + + frameShadow + Sunken + + + totalSteps + 20 + + + indicatorFollowsStyle + false + + + + + name + Spacer2 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QPushButton + + name + cancel + + + sizePolicy + + 1 + 7 + + + + palette + + + + 0 + 0 + 0 + + + 181 + 222 + 178 + + + 255 + 255 + 255 + + + 218 + 238 + 216 + + + 90 + 111 + 89 + + + 120 + 148 + 118 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 174 + 222 + 158 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + 128 + 128 + 128 + + + 181 + 222 + 178 + + + 255 + 255 + 255 + + + 207 + 255 + 204 + + + 90 + 111 + 89 + + + 120 + 148 + 118 + + + 128 + 128 + 128 + + + 255 + 255 + 255 + + + 128 + 128 + 128 + + + 255 + 255 + 255 + + + 174 + 222 + 158 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + 0 + 0 + 0 + + + 181 + 222 + 178 + + + 255 + 255 + 255 + + + 207 + 255 + 204 + + + 90 + 111 + 89 + + + 120 + 148 + 118 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 174 + 222 + 158 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + + text + Cancel + + + default + true + + + + + diff --git a/core/launcher/shutdownimpl.cpp b/core/launcher/shutdownimpl.cpp new file mode 100644 index 0000000..06ed756 --- a/dev/null +++ b/core/launcher/shutdownimpl.cpp @@ -0,0 +1,95 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "shutdownimpl.h" + +#include + +#include +#include +#include +#include +#include + + + +#include +ShutdownImpl::ShutdownImpl( QWidget* parent, const char *name, WFlags fl ) + : Shutdown( parent, name, fl ) +{ + timer = new QTimer( this ); + connect( timer, SIGNAL(timeout()), this, SLOT(timeout()) ); + + connect( ButtonGroup1, SIGNAL(clicked(int)), this, SLOT(buttonClicked(int)) ); + connect( cancel, SIGNAL(clicked()), this, SLOT(cancelClicked()) ); + + progressBar->hide(); + Global::hideInputMethod(); +#ifdef QT_QWS_CUSTOM + QPushButton *sb = Shutdown::shutdown; + sb->hide(); +#endif +} + +void ShutdownImpl::buttonClicked( int b ) +{ + progress = 0; + switch ( b ) { + case 1: + operation = ShutdownSystem; + break; + case 2: + operation = RebootSystem; + break; + case 3: + operation = RestartDesktop; + break; + case 4: + operation = TerminateDesktop; + break; + } + info->hide(); + progressBar->show(); + timer->start( 300 ); + timeout(); +} + +void ShutdownImpl::cancelClicked() +{ + progressBar->hide(); + info->show(); + if ( timer->isActive() ) + timer->stop(); + else + close(); +} + +void ShutdownImpl::timeout() +{ + if ( (progress+=2) > progressBar->totalSteps() ) { + progressBar->hide(); + timer->stop(); + emit shutdown( operation ); + } else { + progressBar->setProgress( progress ); + } +} + + diff --git a/core/launcher/shutdownimpl.h b/core/launcher/shutdownimpl.h new file mode 100644 index 0000000..54668f3 --- a/dev/null +++ b/core/launcher/shutdownimpl.h @@ -0,0 +1,50 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef SHUTDOWNIMPL_H +#define SHUTDOWNIMPL_H + +#include "shutdown.h" + +class QTimer; + +class ShutdownImpl : public Shutdown +{ + Q_OBJECT +public: + ShutdownImpl( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + + enum Type { ShutdownSystem, RebootSystem, RestartDesktop, TerminateDesktop }; + +signals: + void shutdown( ShutdownImpl::Type ); + +private slots: + void buttonClicked( int ); + void cancelClicked(); + void timeout(); + +private: + QTimer *timer; + int progress; + Type operation; +}; + +#endif + diff --git a/core/launcher/sidething.cpp b/core/launcher/sidething.cpp new file mode 100644 index 0000000..821c9d5 --- a/dev/null +++ b/core/launcher/sidething.cpp @@ -0,0 +1,75 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "sidething.h" + +#include + +#include +#include +#include + + +void PopupWithLaunchSideThing::setFrameRect( const QRect &r ) +{ + fr = r; + QPopupMenu::setFrameRect( r ); +} + + +void PopupWithLaunchSideThing::paintEvent( QPaintEvent *event ) +{ + QPainter paint( this ); + + if ( !contentsRect().contains( event->rect() ) ) { + + QPopupMenu::setFrameRect( fr ); + int oldLW = lineWidth(); + setUpdatesEnabled(FALSE); + setLineWidth(oldLW); + setUpdatesEnabled(TRUE); + + paint.save(); + paint.setClipRegion( event->region().intersect( frameRect() ) ); + QPixmap pm( Resource::loadPixmap( sidePixmap ) ); + paint.drawPixmap( 2, fr.height() - pm.height() - 2, pm ); +// Need to draw a filled rectangle that extends the colour from the +// end of the pixmap up to the top of the popupmenu +// paint.fillRect(); + drawFrame( &paint ); + paint.restore(); + + } + if ( event->rect().intersects( contentsRect() ) /* && + (fstyle & MShape) != HLine && (fstyle & MShape) != VLine */ ) { + + QPopupMenu::setFrameRect( QRect(fr.left() + 21, fr.top(), fr.width() - 21, fr.height()) ); + int oldLW = lineWidth(); + setUpdatesEnabled(FALSE); + setLineWidth(oldLW); + setUpdatesEnabled(TRUE); + + paint.setClipRegion( event->region().intersect( contentsRect() ) ); + drawContents( &paint ); + } + +} + + diff --git a/core/launcher/sidething.h b/core/launcher/sidething.h new file mode 100644 index 0000000..666a59d --- a/dev/null +++ b/core/launcher/sidething.h @@ -0,0 +1,43 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __SIDE_THING_H__ +#define __SIDE_THING_H__ + + +#include "startmenu.h" + + +class PopupWithLaunchSideThing : public StartPopupMenu +{ +Q_OBJECT +public: + PopupWithLaunchSideThing( QWidget *parent, QString *pixmap ) : StartPopupMenu( parent ), sidePixmap(*pixmap) { } + +protected: + void setFrameRect( const QRect & ); + void paintEvent( QPaintEvent *event ); + QRect fr; + QString sidePixmap; +}; + + +#endif // __SIDE_THING_H__ + diff --git a/core/launcher/stabmon.cpp b/core/launcher/stabmon.cpp new file mode 100644 index 0000000..2911a1c --- a/dev/null +++ b/core/launcher/stabmon.cpp @@ -0,0 +1,92 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + + +#include "stabmon.h" + +#include + +#include +#include + +#include +#include +#include + +SysFileMonitor::SysFileMonitor(QObject* parent) : + QObject(parent) +{ + startTimer(2000); +} + +const char * stab0 = "/var/run/stab"; +const char * stab1 = "/var/state/pcmcia/stab"; +const char * stab2 = "/var/lib/pcmcia/stab"; + +void SysFileMonitor::timerEvent(QTimerEvent*) +{ + struct stat s; + + static const char * tab [] = { + stab0, + stab1, + stab2 + }; + static const int nstab = sizeof(tab)/sizeof(const char *); + static int last[nstab]; + + bool ch = FALSE; + for ( int i=0; i + +class SysFileMonitor : public QObject { +public: + SysFileMonitor(QObject* parent); +protected: + void timerEvent(QTimerEvent*); +}; + +#endif diff --git a/core/launcher/startmenu.cpp b/core/launcher/startmenu.cpp new file mode 100644 index 0000000..54bdfcc --- a/dev/null +++ b/core/launcher/startmenu.cpp @@ -0,0 +1,171 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "startmenu.h" +#include "sidething.h" +#include "mrulist.h" +#include "info.h" + +#include +#include +#include +#include +#include + +#include + +#include + + +// #define USE_CONFIG_FILE + + +StartMenu::StartMenu(QWidget *parent) : QLabel( parent ) +{ + loadOptions(); + + setPixmap( Resource::loadPixmap( startButtonPixmap ) ); + setFocusPolicy( NoFocus ); + //setFlat( startButtonIsFlat ); + + apps = new AppLnkSet( QPEApplication::qpeDir() + "apps" ); + + createMenu(); +} + + +void StartMenu::mousePressEvent( QMouseEvent * ) +{ + launch(); + if (desktopInfo) + desktopInfo->menuClicked(); +} + + +StartMenu::~StartMenu() +{ + delete apps; +} + + +void StartMenu::loadOptions() +{ +#ifdef USE_CONFIG_FILE + // Read configuration file + Config config("StartMenu"); + config.setGroup( "StartMenu" ); + QString tmpBoolString1 = config.readEntry( "UseWidePopupMenu", "FALSE" ); + useWidePopupMenu = ( tmpBoolString1 == "TRUE" ) ? TRUE : FALSE; + QString tmpBoolString2 = config.readEntry( "StartButtonIsFlat", "TRUE" ); + startButtonIsFlat = ( tmpBoolString2 == "TRUE" ) ? TRUE : FALSE; + QString tmpBoolString3 = config.readEntry( "UseMRUList", "TRUE" ); + popupMenuSidePixmap = config.readEntry( "PopupMenuSidePixmap", "sidebar" ); + startButtonPixmap = config.readEntry( "StartButtonPixmap", "go" ); +#else + // Basically just #include the .qpe_menu.conf file settings + useWidePopupMenu = FALSE; + popupMenuSidePixmap = "sidebar"; + startButtonIsFlat = TRUE; + startButtonPixmap = "go"; +#endif +} + + +void StartMenu::createMenu() +{ + if ( useWidePopupMenu ) + launchMenu = new PopupWithLaunchSideThing( this, &popupMenuSidePixmap ); + else + launchMenu = new StartPopupMenu( this ); + + loadMenu( apps, launchMenu ); + +} + +void StartMenu::itemSelected( int id ) +{ + const AppLnk *app = apps->find( id ); + if ( app ) + app->execute(); +} + +bool StartMenu::loadMenu( AppLnkSet *folder, QPopupMenu *menu ) +{ + bool result = FALSE; + + QStringList typs = folder->types(); + QDict typpop; + for (QStringList::Iterator tit=typs.begin(); tit!=typs.end(); ++tit) { + if ( !(*tit).isEmpty() ) { + QPopupMenu *new_menu = new StartPopupMenu( menu ); + typpop.insert(*tit, new_menu); + connect( new_menu, SIGNAL(activated(int)), SLOT(itemSelected(int)) ); + menu->insertItem( folder->typePixmap(*tit), *tit, new_menu ); + } + } + + QListIterator it( folder->children() ); + for ( ; it.current(); ++it ) { + AppLnk *app = it.current(); + if ( app->type() == "Separator" ) { + menu->insertSeparator(); + } else { + QString t = app->type(); + QPopupMenu* pmenu = typpop.find(t); + if ( !pmenu ) + pmenu = menu; + pmenu->insertItem( app->pixmap(), app->name(), app->id() ); + result=TRUE; + } + } + + if ( result ) + connect( menu, SIGNAL(activated(int)), SLOT(itemSelected(int)) ); + + return result; +} + + +void StartMenu::launch() +{ + int y = mapToGlobal( QPoint() ).y() - launchMenu->sizeHint().height(); + + if ( launchMenu->isVisible() ) + launchMenu->hide(); + else + launchMenu->popup( QPoint( 1, y ) ); +} + +const AppLnk* StartMenu::execToLink(const QString& appname) +{ + const AppLnk* a = apps->findExec( appname ); + return a; +} + +void StartPopupMenu::keyPressEvent( QKeyEvent *e ) +{ + if ( e->key() == Key_F33 || e->key() == Key_Space ) { + // "OK" button, little hacky + QKeyEvent ke(QEvent::KeyPress, Key_Enter, 13, 0); + QPopupMenu::keyPressEvent( &ke ); + } else { + QPopupMenu::keyPressEvent( e ); + } +} diff --git a/core/launcher/startmenu.h b/core/launcher/startmenu.h new file mode 100644 index 0000000..a02f39e --- a/dev/null +++ b/core/launcher/startmenu.h @@ -0,0 +1,76 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __START_MENU_H__ +#define __START_MENU_H__ + +#include +#include +#include +#include + + +class AppLnkSet; +class AppLnk; + +class StartPopupMenu : public QPopupMenu +{ +public: + StartPopupMenu( QWidget *parent ) : QPopupMenu( parent ) {} +protected: + void keyPressEvent( QKeyEvent *e ); +}; + +class StartMenu : public QLabel { + Q_OBJECT +public: + StartMenu( QWidget * ); + ~StartMenu(); + + const AppLnk* execToLink(const QString& appname); + +public: + StartPopupMenu *launchMenu; + +public slots: + void launch( ); + void loadOptions( ); + void createMenu( ); + +protected slots: + void itemSelected( int id ); + +protected: + virtual void mousePressEvent( QMouseEvent * ); + +private: + bool loadMenu( AppLnkSet *folder, QPopupMenu *menu ); + +private: + bool useWidePopupMenu; + QString popupMenuSidePixmap; + + bool startButtonIsFlat; + QString startButtonPixmap; + + AppLnkSet *apps; +}; + +#endif // __START_MENU_H__ diff --git a/core/launcher/syncdialog.ui b/core/launcher/syncdialog.ui new file mode 100644 index 0000000..141f123 --- a/dev/null +++ b/core/launcher/syncdialog.ui @@ -0,0 +1,228 @@ + +SyncDialog + + QDialog + + name + SyncDialog + + + geometry + + 0 + 0 + 210 + 244 + + + + caption + Syncing + + + sizeGripEnabled + true + + + + margin + 11 + + + spacing + 6 + + + + name + Spacer10 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QLayoutWidget + + name + Layout3 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + TextLabel1 + + + text + Syncing + + + alignment + AlignCenter + + + hAlign + + + + QLabel + + name + whatLabel + + + text + <b>Contacts</b> + + + + + + + name + Spacer11 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QLayoutWidget + + name + Layout4 + + + + margin + 0 + + + spacing + 6 + + + + name + Spacer4 + + + orientation + Horizontal + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QPushButton + + name + buttonCancel + + + text + &Cancel + + + autoDefault + true + + + + + name + Spacer5 + + + orientation + Horizontal + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + + name + Spacer12 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + + buttonCancel + clicked() + SyncDialog + reject() + + + diff --git a/core/launcher/systray.cpp b/core/launcher/systray.cpp new file mode 100644 index 0000000..ad1553f --- a/dev/null +++ b/core/launcher/systray.cpp @@ -0,0 +1,107 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include "quicklauncher.h" +#include "systray.h" + +#include + +#ifdef SINGLE_APP +#include "clockappletimpl.h" +#endif + +SysTray::SysTray( QWidget *parent ) : QFrame( parent ), layout(0) +{ + //setFrameStyle( QFrame::Panel | QFrame::Sunken ); + loadApplets(); +} + +void SysTray::loadApplets() +{ +#ifndef SINGLE_APP + QValueList::Iterator mit; + for ( mit = appletList.begin(); mit != appletList.end(); ++mit ) { + (*mit).iface->release(); + (*mit).library->unload(); + delete (*mit).library; + } + appletList.clear(); + if ( layout ) + delete layout; + layout = new QHBoxLayout( this ); + + QString path = QPEApplication::qpeDir() + "/plugins/applets"; + QDir dir( path, "lib*.so" ); + QStringList list = dir.entryList(); + QStringList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + TaskbarAppletInterface *iface = 0; + QLibrary *lib = new QLibrary( path + "/" + *it ); + if ( lib->queryInterface( IID_TaskbarApplet, (QUnknownInterface**)&iface ) == QS_OK ) { + TaskbarApplet applet; + applet.library = lib; + applet.iface = iface; + applet.applet = applet.iface->applet( this ); + positionApplet( applet ); + QString lang = getenv( "LANG" ); + QTranslator * trans = new QTranslator(qApp); + QString type = (*it).left( (*it).find(".") ); + QString tfn = QPEApplication::qpeDir()+"/i18n/"+lang+"/"+type+".qm"; + qDebug("tr fpr sysapplet: %s", tfn.latin1() ); + if ( trans->load( tfn )) + qApp->installTranslator( trans ); + else + delete trans; + } else { + delete lib; + } + } +#else + layout = new QHBoxLayout( this ); + TaskbarApplet applet; + applet.iface = new ClockAppletImpl(); + applet.applet = applet.iface->applet( this ); + positionApplet( applet ); +#endif +} + +void SysTray::positionApplet( const TaskbarApplet &a ) +{ + int p = 0; + QValueList::Iterator it; + for ( it = appletList.begin(); it != appletList.end(); ++it ) { + if ( (*it).iface->position() > a.iface->position() ) + break; + p += 2; + } + + appletList.insert( it, a ); + layout->insertWidget( p, a.applet ); + layout->insertSpacing( p, 1 ); +} + diff --git a/core/launcher/systray.h b/core/launcher/systray.h new file mode 100644 index 0000000..0aed348 --- a/dev/null +++ b/core/launcher/systray.h @@ -0,0 +1,58 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __SYSTRAY_H__ +#define __SYSTRAY_H__ + +#include + +#include +#include + +class QHBoxLayout; +class QLibrary; + +struct TaskbarApplet +{ +#ifndef QT_NO_COMPONENT + QLibrary *library; +#endif + TaskbarAppletInterface *iface; + QWidget *applet; +}; + +class SysTray : public QFrame { + Q_OBJECT +public: + SysTray( QWidget *parent ); + + void loadApplets(); + +private: + void positionApplet( const TaskbarApplet &a ); + +private: + QHBoxLayout *layout; + QValueList appletList; +}; + + +#endif // __SYSTRAY_H__ + diff --git a/core/launcher/taskbar.cpp b/core/launcher/taskbar.cpp new file mode 100644 index 0000000..d7f36bd --- a/dev/null +++ b/core/launcher/taskbar.cpp @@ -0,0 +1,314 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "startmenu.h" +#include "inputmethods.h" +#include "mrulist.h" +#include "systray.h" +#include "calibrate.h" +#include "wait.h" +#include "appicons.h" + +#include "taskbar.h" +#include "desktop.h" + +#include +#include +#include +#ifdef QT_QWS_CUSTOM +#include +#endif + +#include +#include +#include +#include +#include + +#if defined( Q_WS_QWS ) +#include +#include +#endif + + +#define FACTORY(T) \ + static QWidget *new##T( bool maximized ) { \ + QWidget *w = new T( 0, "test", QWidget::WDestructiveClose | QWidget::WGroupLeader ); \ + if ( maximized ) { \ + if ( qApp->desktop()->width() <= 350 ) { \ + w->showMaximized(); \ + } else { \ + w->resize( QSize( 300, 300 ) ); \ + } \ + } \ + w->show(); \ + return w; \ + } + + +#ifdef SINGLE_APP +#define APP(a,b,c,d) FACTORY(b) +#include "../taskbar/apps.h" +#undef APP +#endif // SINGLE_APP + +static Global::Command builtins[] = { + +#ifdef SINGLE_APP +#define APP(a,b,c,d) { a, new##b, c }, +#include "../taskbar/apps.h" +#undef APP +#endif + +#if defined(QT_QWS_IPAQ) || defined(QT_QWS_CASSIOPEIA) || defined(QT_QWS_EBX) + { "calibrate", TaskBar::calibrate, 1, 0 }, +#endif +#if !defined(QT_QWS_CASSIOPEIA) + { "shutdown", Global::shutdown, 1, 0 }, +// { "run", run, 1, 0 }, +#endif + + { 0, TaskBar::calibrate, 0, 0 }, +}; + +static bool initNumLock() +{ +#ifdef QPE_INITIAL_NUMLOCK_STATE + QPE_INITIAL_NUMLOCK_STATE +#endif + return FALSE; +} + +class LockKeyState : public QWidget +{ +public: + LockKeyState( QWidget *parent ) : + QWidget(parent), + nl(initNumLock()), cl(FALSE) + { + nl_pm = Resource::loadPixmap("numlock"); + cl_pm = Resource::loadPixmap("capslock"); + } + QSize sizeHint() const + { + return QSize(nl_pm.width()+2,nl_pm.width()+nl_pm.height()+1); + } + void toggleNumLockState() + { + nl = !nl; repaint(); + } + void toggleCapsLockState() + { + cl = !cl; repaint(); + } + void paintEvent( QPaintEvent * ) + { + int y = (height()-sizeHint().height())/2; + QPainter p(this); + if ( nl ) + p.drawPixmap(1,y,nl_pm); + if ( cl ) + p.drawPixmap(1,y+nl_pm.height()+1,cl_pm); + } +private: + QPixmap nl_pm, cl_pm; + bool nl, cl; +}; + +TaskBar::~TaskBar() +{ +} + + +TaskBar::TaskBar() : QHBox(0, 0, WStyle_Customize | WStyle_Tool | WStyle_StaysOnTop | WGroupLeader) +{ + Global::setBuiltinCommands(builtins); + + sm = new StartMenu( this ); + + inputMethods = new InputMethods( this ); + connect( inputMethods, SIGNAL(inputToggled(bool)), + this, SLOT(calcMaxWindowRect()) ); + //new QuickLauncher( this ); + + stack = new QWidgetStack( this ); + stack->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ) ); + label = new QLabel(stack); + + mru = new MRUList( stack ); + stack->raiseWidget( mru ); + + waitIcon = new Wait( this ); + (void) new AppIcons( this ); + + sysTray = new SysTray( this ); + + // ## make customizable in some way? +#ifdef QT_QWS_CUSTOM + lockState = new LockKeyState( this ); +#else + lockState = 0; +#endif + +#if defined(Q_WS_QWS) +#if !defined(QT_NO_COP) + QCopChannel *channel = new QCopChannel( "QPE/TaskBar", this ); + connect( channel, SIGNAL(received(const QCString&, const QByteArray&)), + this, SLOT(receive(const QCString&, const QByteArray&)) ); +#endif +#endif + waitTimer = new QTimer( this ); + connect( waitTimer, SIGNAL( timeout() ), this, SLOT( stopWait() ) ); + clearer = new QTimer( this ); + QObject::connect(clearer, SIGNAL(timeout()), SLOT(clearStatusBar())); + QObject::connect(clearer, SIGNAL(timeout()), sysTray, SLOT(show())); +} + +void TaskBar::setStatusMessage( const QString &text ) +{ + label->setText( text ); + stack->raiseWidget( label ); + if ( sysTray && ( label->fontMetrics().width( text ) > label->width() ) ) + sysTray->hide(); + clearer->start( 3000 ); +} + +void TaskBar::clearStatusBar() +{ + label->clear(); + stack->raiseWidget( mru ); +} + +void TaskBar::startWait() +{ + waitIcon->setWaiting( true ); + // a catchall stop after 10 seconds... + waitTimer->start( 10 * 1000, true ); +} + +void TaskBar::stopWait(const QString& app) +{ + waitTimer->stop(); + mru->addTask(sm->execToLink(app)); + waitIcon->setWaiting( false ); +} + +void TaskBar::stopWait() +{ + waitTimer->stop(); + waitIcon->setWaiting( false ); +} + +void TaskBar::resizeEvent( QResizeEvent *e ) +{ + QHBox::resizeEvent( e ); + calcMaxWindowRect(); +} + +void TaskBar::styleChange( QStyle &s ) +{ + QHBox::styleChange( s ); + calcMaxWindowRect(); +} + +void TaskBar::calcMaxWindowRect() +{ +#ifdef Q_WS_QWS + QRect wr; + int displayWidth = qApp->desktop()->width(); + QRect ir = inputMethods->inputRect(); + if ( ir.isValid() ) { + wr.setCoords( 0, 0, displayWidth-1, ir.top()-1 ); + } else { + wr.setCoords( 0, 0, displayWidth-1, y()-1 ); + } + +#if QT_VERSION < 300 + QWSServer::setMaxWindowRect( qt_screen->mapToDevice(wr, + QSize(qt_screen->width(),qt_screen->height())) + ); +#else + QWSServer::setMaxWindowRect( wr ); +#endif +#endif +} + +void TaskBar::receive( const QCString &msg, const QByteArray &data ) +{ + QDataStream stream( data, IO_ReadOnly ); + if ( msg == "message(QString)" ) { + QString text; + stream >> text; + setStatusMessage( text ); + } else if ( msg == "hideInputMethod()" ) { + inputMethods->hideInputMethod(); + } else if ( msg == "showInputMethod()" ) { + inputMethods->showInputMethod(); + } else if ( msg == "reloadInputMethods()" ) { + inputMethods->loadInputMethods(); + } else if ( msg == "reloadApplets()" ) { + sysTray->loadApplets(); + } else if ( msg == "soundAlarm()" ) { + Desktop::soundAlarm(); + } +#ifdef CUSTOM_LEDS + else if ( msg == "setLed(int,bool)" ) { + int led, status; + stream >> led >> status; + CUSTOM_LEDS( led, status ); + } +#endif +} + +QWidget *TaskBar::calibrate(bool) +{ +#ifdef Q_WS_QWS + Calibrate *c = new Calibrate; + c->show(); + return c; +#else + return 0; +#endif +} + +void TaskBar::toggleNumLockState() +{ + if ( lockState ) lockState->toggleNumLockState(); +} + +void TaskBar::toggleCapsLockState() +{ + if ( lockState ) lockState->toggleCapsLockState(); +} + +void TaskBar::toggleSymbolInput() +{ + if ( inputMethods->currentShown() == "Unicode" ) { + inputMethods->hideInputMethod(); + } else { + inputMethods->showInputMethod("Unicode"); + } +} + +bool TaskBar::recoverMemory() +{ + return mru->quitOldApps(); +} + diff --git a/core/launcher/taskbar.h b/core/launcher/taskbar.h new file mode 100644 index 0000000..cdeb3c7 --- a/dev/null +++ b/core/launcher/taskbar.h @@ -0,0 +1,86 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __TASKBAR_H__ +#define __TASKBAR_H__ + +#ifdef QT_QWS_CUSTOM +#include +#endif + +#include + +class QLabel; +class QTimer; +class InputMethods; +class Wait; +class SysTray; +class MRUList; +class QWidgetStack; +class QTimer; +class QLabel; +class StartMenu; +class LockKeyState; + +class TaskBar : public QHBox { + Q_OBJECT +public: + TaskBar(); + ~TaskBar(); + + static QWidget *calibrate( bool ); + + bool recoverMemory(); + + StartMenu *startMenu() const { return sm; } +public slots: + void startWait(); + void stopWait(const QString&); + void stopWait(); + void clearStatusBar(); + void toggleNumLockState(); + void toggleCapsLockState(); + void toggleSymbolInput(); + +protected: + void resizeEvent( QResizeEvent * ); + void styleChange( QStyle & ); + void setStatusMessage( const QString &text ); + +private slots: + void calcMaxWindowRect(); + void receive( const QCString &msg, const QByteArray &data ); + +private: + + QTimer *waitTimer; + Wait *waitIcon; + InputMethods *inputMethods; + SysTray *sysTray; + MRUList *mru; + QWidgetStack *stack; + QTimer *clearer; + QLabel *label; + LockKeyState* lockState; + StartMenu *sm; +}; + + +#endif // __TASKBAR_H__ diff --git a/core/launcher/transferserver.cpp b/core/launcher/transferserver.cpp new file mode 100644 index 0000000..87a49eb --- a/dev/null +++ b/core/launcher/transferserver.cpp @@ -0,0 +1,1245 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#define _XOPEN_SOURCE +#include +#include +#include +#include + +#if defined(_OS_LINUX_) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include + +#include "transferserver.h" + +const int block_size = 51200; + +TransferServer::TransferServer( Q_UINT16 port, QObject *parent = 0, + const char* name = 0) + : QServerSocket( port, 1, parent, name ) +{ + if ( !ok() ) + qWarning( "Failed to bind to port %d", port ); +} + +TransferServer::~TransferServer() +{ + +} + +void TransferServer::newConnection( int socket ) +{ + (void) new ServerPI( socket, this ); +} + +bool accessAuthorized(QHostAddress peeraddress) +{ + Config cfg("Security"); + cfg.setGroup("Sync"); + uint auth_peer = cfg.readNumEntry("auth_peer",0xc0a80100); + uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits",24); + bool ok = (peeraddress.ip4Addr() & (((1<An attempt to access this device from %1 has been denied.") + .arg(peeraddress.toString())); + } + */ + return ok; +} + +ServerPI::ServerPI( int socket, QObject *parent = 0, const char* name = 0 ) + : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ) +{ + state = Connected; + + setSocket( socket ); + + peerport = peerPort(); + peeraddress = peerAddress(); + +#ifndef INSECURE + if ( !accessAuthorized(peeraddress) ) { + state = Forbidden; + startTimer( 0 ); + } else +#endif + { + connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); + connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); + + passiv = FALSE; + for( int i = 0; i < 4; i++ ) + wait[i] = FALSE; + + send( "220 Qtopia transfer service ready!" ); + state = Wait_USER; + + dtp = new ServerDTP( this ); + connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) ); + connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) ); + connect( dtp, SIGNAL( error( int ) ), SLOT( dtpError( int ) ) ); + + + directory = QDir::currentDirPath(); + + static int p = 1024; + + while ( !serversocket || !serversocket->ok() ) { + delete serversocket; + serversocket = new ServerSocket( ++p, this ); + } + connect( serversocket, SIGNAL( newIncomming( int ) ), + SLOT( newConnection( int ) ) ); + } +} + +ServerPI::~ServerPI() +{ + +} + +void ServerPI::connectionClosed() +{ + // qDebug( "Debug: Connection closed" ); + delete this; +} + +void ServerPI::send( const QString& msg ) +{ + QTextStream os( this ); + os << msg << endl; + //qDebug( "Reply: %s", msg.latin1() ); +} + +void ServerPI::read() +{ + while ( canReadLine() ) + process( readLine().stripWhiteSpace() ); +} + +bool ServerPI::checkUser( const QString& user ) +{ + if ( user.isEmpty() ) return FALSE; + + struct passwd *pw; + pw = getpwuid( geteuid() ); + QString euser = QString::fromLocal8Bit( pw->pw_name ); + return user == euser; +} + +bool ServerPI::checkPassword( const QString& /* password */ ) +{ + // ### HACK for testing on local host + return true; + + /* + struct passwd *pw = 0; + struct spwd *spw = 0; + + pw = getpwuid( geteuid() ); + spw = getspnam( pw->pw_name ); + + QString cpwd = QString::fromLocal8Bit( pw->pw_passwd ); + if ( cpwd == "x" && spw ) + cpwd = QString::fromLocal8Bit( spw->sp_pwdp ); + + QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) ); + return cpwd == cpassword; +*/ +} + +bool ServerPI::checkReadFile( const QString& file ) +{ + QString filename; + + if ( file[0] != "/" ) + filename = directory.path() + "/" + file; + else + filename = file; + + QFileInfo fi( filename ); + return ( fi.exists() && fi.isReadable() ); +} + +bool ServerPI::checkWriteFile( const QString& file ) +{ + QString filename; + + if ( file[0] != "/" ) + filename = directory.path() + "/" + file; + else + filename = file; + + QFileInfo fi( filename ); + + if ( fi.exists() ) + if ( !QFile( filename ).remove() ) + return FALSE; + return TRUE; +} + +void ServerPI::process( const QString& message ) +{ + //qDebug( "Command: %s", message.latin1() ); + + // split message using "," as separator + QStringList msg = QStringList::split( " ", message ); + if ( msg.isEmpty() ) return; + + // command token + QString cmd = msg[0].upper(); + + // argument token + QString arg; + if ( msg.count() >= 2 ) + arg = msg[1]; + + // full argument string + QString args; + if ( msg.count() >= 2 ) { + QStringList copy( msg ); + // FIXME: for Qt3 + // copy.pop_front() + copy.remove( copy.begin() ); + args = copy.join( " " ); + } + + //qDebug( "args: %s", args.latin1() ); + + // we always respond to QUIT, regardless of state + if ( cmd == "QUIT" ) { + send( "211 Good bye!" ); + delete this; + return; + } + + // connected to client + if ( Connected == state ) + return; + + // waiting for user name + if ( Wait_USER == state ) { + + if ( cmd != "USER" || msg.count() < 2 || !checkUser( arg ) ) { + send( "530 Please login with USER and PASS" ); + return; + } + send( "331 User name ok, need password" ); + state = Wait_PASS; + return; + } + + // waiting for password + if ( Wait_PASS == state ) { + + if ( cmd != "PASS" || !checkPassword( arg ) ) { + //if ( cmd != "PASS" || msg.count() < 2 || !checkPassword( arg ) ) { + send( "530 Please login with USER and PASS" ); + return; + } + send( "230 User logged in, proceed" ); + state = Ready; + return; + } + + // ACCESS CONTROL COMMANDS + + + // account (ACCT) + if ( cmd == "ACCT" ) { + // even wu-ftp does not support it + send( "502 Command not implemented" ); + } + + // change working directory (CWD) + else if ( cmd == "CWD" ) { + + if ( !args.isEmpty() ) { + if ( directory.cd( args, TRUE ) ) + send( "250 Requested file action okay, completed" ); + else + send( "550 Requested action not taken" ); + } + else + send( "500 Syntax error, command unrecognized" ); + } + + // change to parent directory (CDUP) + else if ( cmd == "CDUP" ) { + if ( directory.cdUp() ) + send( "250 Requested file action okay, completed" ); + else + send( "550 Requested action not taken" ); + } + + // structure mount (SMNT) + else if ( cmd == "SMNT" ) { + // even wu-ftp does not support it + send( "502 Command not implemented" ); + } + + // reinitialize (REIN) + else if ( cmd == "REIN" ) { + // even wu-ftp does not support it + send( "502 Command not implemented" ); + } + + + // TRANSFER PARAMETER COMMANDS + + + // data port (PORT) + else if ( cmd == "PORT" ) { + if ( parsePort( arg ) ) + send( "200 Command okay" ); + else + send( "500 Syntax error, command unrecognized" ); + } + + // passive (PASV) + else if ( cmd == "PASV" ) { + passiv = TRUE; + send( "227 Entering Passive Mode (" + + address().toString().replace( QRegExp( "\\." ), "," ) + "," + + QString::number( ( serversocket->port() ) >> 8 ) + "," + + QString::number( ( serversocket->port() ) & 0xFF ) +")" ); + } + + // representation type (TYPE) + else if ( cmd == "TYPE" ) { + if ( arg.upper() == "A" || arg.upper() == "I" ) + send( "200 Command okay" ); + else + send( "504 Command not implemented for that parameter" ); + } + + // file structure (STRU) + else if ( cmd == "STRU" ) { + if ( arg.upper() == "F" ) + send( "200 Command okay" ); + else + send( "504 Command not implemented for that parameter" ); + } + + // transfer mode (MODE) + else if ( cmd == "MODE" ) { + if ( arg.upper() == "S" ) + send( "200 Command okay" ); + else + send( "504 Command not implemented for that parameter" ); + } + + + // FTP SERVICE COMMANDS + + + // retrieve (RETR) + else if ( cmd == "RETR" ) + if ( !args.isEmpty() && checkReadFile( absFilePath( args ) ) + || backupRestoreGzip( absFilePath( args ) ) ) { + send( "150 File status okay" ); + sendFile( absFilePath( args ) ); + } + else { + qDebug("550 Requested action not taken"); + send( "550 Requested action not taken" ); + } + + // store (STOR) + else if ( cmd == "STOR" ) + if ( !args.isEmpty() && checkWriteFile( absFilePath( args ) ) ) { + send( "150 File status okay" ); + retrieveFile( absFilePath( args ) ); + } + else + send( "550 Requested action not taken" ); + + // store unique (STOU) + else if ( cmd == "STOU" ) { + send( "502 Command not implemented" ); + } + + // append (APPE) + else if ( cmd == "APPE" ) { + send( "502 Command not implemented" ); + } + + // allocate (ALLO) + else if ( cmd == "ALLO" ) { + send( "200 Command okay" ); + } + + // restart (REST) + else if ( cmd == "REST" ) { + send( "502 Command not implemented" ); + } + + // rename from (RNFR) + else if ( cmd == "RNFR" ) { + renameFrom = QString::null; + if ( args.isEmpty() ) + send( "500 Syntax error, command unrecognized" ); + else { + QFile file( absFilePath( args ) ); + if ( file.exists() ) { + send( "350 File exists, ready for destination name" ); + renameFrom = absFilePath( args ); + } + else + send( "550 Requested action not taken" ); + } + } + + // rename to (RNTO) + else if ( cmd == "RNTO" ) { + if ( lastCommand != "RNFR" ) + send( "503 Bad sequence of commands" ); + else if ( args.isEmpty() ) + send( "500 Syntax error, command unrecognized" ); + else { + QDir dir( absFilePath( args ) ); + if ( dir.rename( renameFrom, absFilePath( args ), TRUE ) ) + send( "250 Requested file action okay, completed." ); + else + send( "550 Requested action not taken" ); + } + } + + // abort (ABOR) + else if ( cmd.contains( "ABOR" ) ) { + dtp->close(); + if ( dtp->dtpMode() != ServerDTP::Idle ) + send( "426 Connection closed; transfer aborted" ); + else + send( "226 Closing data connection" ); + } + + // delete (DELE) + else if ( cmd == "DELE" ) { + if ( args.isEmpty() ) + send( "500 Syntax error, command unrecognized" ); + else { + QFile file( absFilePath( args ) ) ; + if ( file.remove() ) + send( "250 Requested file action okay, completed" ); + else + send( "550 Requested action not taken" ); + } + } + + // remove directory (RMD) + else if ( cmd == "RMD" ) { + if ( args.isEmpty() ) + send( "500 Syntax error, command unrecognized" ); + else { + QDir dir; + if ( dir.rmdir( absFilePath( args ), TRUE ) ) + send( "250 Requested file action okay, completed" ); + else + send( "550 Requested action not taken" ); + } + } + + // make directory (MKD) + else if ( cmd == "MKD" ) { + if ( args.isEmpty() ) { + qDebug(" Error: no arg"); + send( "500 Syntax error, command unrecognized" ); + } + else { + QDir dir; + if ( dir.mkdir( absFilePath( args ), TRUE ) ) + send( "250 Requested file action okay, completed." ); + else + send( "550 Requested action not taken" ); + } + } + + // print working directory (PWD) + else if ( cmd == "PWD" ) { + send( "257 \"" + directory.path() +"\"" ); + } + + // list (LIST) + else if ( cmd == "LIST" ) { + if ( sendList( absFilePath( args ) ) ) + send( "150 File status okay" ); + else + send( "500 Syntax error, command unrecognized" ); + } + + // size (SIZE) + else if ( cmd == "SIZE" ) { + QString filePath = absFilePath( args ); + QFileInfo fi( filePath ); + bool gzipfile = backupRestoreGzip( filePath ); + if ( !fi.exists() && !gzipfile ) + send( "500 Syntax error, command unrecognized" ); + else { + if ( !gzipfile ) + send( "213 " + QString::number( fi.size() ) ); + else { + Process duproc( QString("du") ); + duproc.addArgument("-s"); + QString in, out; + if ( !duproc.exec(in, out) ) { + qDebug("du process failed; just sending back 1K"); + send( "213 1024"); + } + else { + QString size = out.left( out.find("\t") ); + int guess = size.toInt()/5; + if ( filePath.contains("doc") ) + guess *= 1000; + qDebug("sending back gzip guess of %d", guess); + send( "213 " + QString::number(guess) ); + } + } + } + } + // name list (NLST) + else if ( cmd == "NLST" ) { + send( "502 Command not implemented" ); + } + + // site parameters (SITE) + else if ( cmd == "SITE" ) { + send( "502 Command not implemented" ); + } + + // system (SYST) + else if ( cmd == "SYST" ) { + send( "215 UNIX Type: L8" ); + } + + // status (STAT) + else if ( cmd == "STAT" ) { + send( "502 Command not implemented" ); + } + + // help (HELP ) + else if ( cmd == "HELP" ) { + send( "502 Command not implemented" ); + } + + // noop (NOOP) + else if ( cmd == "NOOP" ) { + send( "200 Command okay" ); + } + + // not implemented + else + send( "502 Command not implemented" ); + + lastCommand = cmd; +} + +bool ServerPI::backupRestoreGzip( const QString &file ) +{ + return (file.find( "backup" ) != -1 && + file.findRev( ".tgz" ) == (int)file.length()-4 ); +} + +bool ServerPI::backupRestoreGzip( const QString &file, QStringList &targets ) +{ + if ( file.find( "backup" ) != -1 && + file.findRev( ".tgz" ) == (int)file.length()-4 ) { + QFileInfo info( file ); + targets = info.dirPath( TRUE ); + qDebug("ServerPI::backupRestoreGzip for %s = %s", file.latin1(), + targets.join(" ").latin1() ); + return true; + } + return false; +} + +void ServerPI::sendFile( const QString& file ) +{ + if ( passiv ) { + wait[SendFile] = TRUE; + waitfile = file; + if ( waitsocket ) + newConnection( waitsocket ); + } + else { + QStringList targets; + if ( backupRestoreGzip( file, targets ) ) + dtp->sendGzipFile( file, targets, peeraddress, peerport ); + else dtp->sendFile( file, peeraddress, peerport ); + } +} + +void ServerPI::retrieveFile( const QString& file ) +{ + if ( passiv ) { + wait[RetrieveFile] = TRUE; + waitfile = file; + if ( waitsocket ) + newConnection( waitsocket ); + } + else { + QStringList targets; + if ( backupRestoreGzip( file, targets ) ) + dtp->retrieveGzipFile( file, peeraddress, peerport ); + else + dtp->retrieveFile( file, peeraddress, peerport ); + } +} + +bool ServerPI::parsePort( const QString& pp ) +{ + QStringList p = QStringList::split( ",", pp ); + if ( p.count() != 6 ) return FALSE; + + // h1,h2,h3,h4,p1,p2 + peeraddress = QHostAddress( ( p[0].toInt() << 24 ) + ( p[1].toInt() << 16 ) + + ( p[2].toInt() << 8 ) + p[3].toInt() ); + peerport = ( p[4].toInt() << 8 ) + p[5].toInt(); + return TRUE; +} + +void ServerPI::dtpCompleted() +{ + dtp->close(); + waitsocket = 0; + send( "226 Closing data connection, file transfer successful" ); +} + +void ServerPI::dtpFailed() +{ + dtp->close(); + waitsocket = 0; + send( "451 Requested action aborted: local error in processing" ); +} + +void ServerPI::dtpError( int ) +{ + dtp->close(); + waitsocket = 0; + send( "451 Requested action aborted: local error in processing" ); +} + +bool ServerPI::sendList( const QString& arg ) +{ + QByteArray listing; + QBuffer buffer( listing ); + + if ( !buffer.open( IO_WriteOnly ) ) + return FALSE; + + QTextStream ts( &buffer ); + QString fn = arg; + + if ( fn.isEmpty() ) + fn = directory.path(); + + QFileInfo fi( fn ); + if ( !fi.exists() ) return FALSE; + + // return file listing + if ( fi.isFile() ) { + ts << fileListing( &fi ) << endl; + } + + // return directory listing + else if ( fi.isDir() ) { + QDir dir( fn ); + const QFileInfoList *list = dir.entryInfoList( QDir::All | QDir::Hidden ); + + QFileInfoListIterator it( *list ); + QFileInfo *info; + + unsigned long total = 0; + while ( ( info = it.current() ) ) { + if ( info->fileName() != "." && info->fileName() != ".." ) + total += info->size(); + ++it; + } + + ts << "total " << QString::number( total / 1024 ) << endl; + + it.toFirst(); + while ( ( info = it.current() ) ) { + if ( info->fileName() == "." || info->fileName() == ".." ) { + ++it; + continue; + } + ts << fileListing( info ) << endl; + ++it; + } + } + + if ( passiv ) { + waitarray = buffer.buffer(); + wait[SendByteArray] = TRUE; + if ( waitsocket ) + newConnection( waitsocket ); + } + else + dtp->sendByteArray( buffer.buffer(), peeraddress, peerport ); + return TRUE; +} + +QString ServerPI::fileListing( QFileInfo *info ) +{ + if ( !info ) return QString::null; + QString s; + + // type char + if ( info->isDir() ) + s += "d"; + else if ( info->isSymLink() ) + s += "l"; + else + s += "-"; + + // permisson string + s += permissionString( info ) + " "; + + // number of hardlinks + int subdirs = 1; + + if ( info->isDir() ) + subdirs = 2; + // FIXME : this is to slow + //if ( info->isDir() ) + //subdirs = QDir( info->absFilePath() ).entryList( QDir::Dirs ).count(); + + s += QString::number( subdirs ).rightJustify( 3, ' ', TRUE ) + " "; + + // owner + s += info->owner().leftJustify( 8, ' ', TRUE ) + " "; + + // group + s += info->group().leftJustify( 8, ' ', TRUE ) + " "; + + // file size in bytes + s += QString::number( info->size() ).rightJustify( 9, ' ', TRUE ) + " "; + + // last modified date + QDate date = info->lastModified().date(); + QTime time = info->lastModified().time(); + s += date.monthName( date.month() ) + " " + + QString::number( date.day() ).rightJustify( 2, ' ', TRUE ) + " " + + QString::number( time.hour() ).rightJustify( 2, '0', TRUE ) + ":" + + QString::number( time.minute() ).rightJustify( 2,'0', TRUE ) + " "; + + // file name + s += info->fileName(); + + return s; +} + +QString ServerPI::permissionString( QFileInfo *info ) +{ + if ( !info ) return QString( "---------" ); + QString s; + + // user + if ( info->permission( QFileInfo::ReadUser ) ) s += "r"; + else s += "-"; + if ( info->permission( QFileInfo::WriteUser ) ) s += "w"; + else s += "-"; + if ( info->permission( QFileInfo::ExeUser ) ) s += "x"; + else s += "-"; + + // group + if ( info->permission( QFileInfo::ReadGroup ) ) s += "r"; + else s += "-"; + if ( info->permission( QFileInfo::WriteGroup ) )s += "w"; + else s += "-"; + if ( info->permission( QFileInfo::ExeGroup ) ) s += "x"; + else s += "-"; + + // exec + if ( info->permission( QFileInfo::ReadOther ) ) s += "r"; + else s += "-"; + if ( info->permission( QFileInfo::WriteOther ) ) s += "w"; + else s += "-"; + if ( info->permission( QFileInfo::ExeOther ) ) s += "x"; + else s += "-"; + + return s; +} + +void ServerPI::newConnection( int socket ) +{ + //qDebug( "New incomming connection" ); + + if ( !passiv ) return; + + if ( wait[SendFile] ) { + QStringList targets; + if ( backupRestoreGzip( waitfile, targets ) ) + dtp->sendGzipFile( waitfile, targets ); + else + dtp->sendFile( waitfile ); + dtp->setSocket( socket ); + } + else if ( wait[RetrieveFile] ) { + qDebug("check retrieve file"); + if ( backupRestoreGzip( waitfile ) ) + dtp->retrieveGzipFile( waitfile ); + else + dtp->retrieveFile( waitfile ); + dtp->setSocket( socket ); + } + else if ( wait[SendByteArray] ) { + dtp->sendByteArray( waitarray ); + dtp->setSocket( socket ); + } + else if ( wait[RetrieveByteArray] ) { + qDebug("retrieve byte array"); + dtp->retrieveByteArray(); + dtp->setSocket( socket ); + } + else + waitsocket = socket; + + for( int i = 0; i < 4; i++ ) + wait[i] = FALSE; +} + +QString ServerPI::absFilePath( const QString& file ) +{ + if ( file.isEmpty() ) return file; + + QString filepath( file ); + if ( file[0] != "/" ) + filepath = directory.path() + "/" + file; + + return filepath; +} + + +void ServerPI::timerEvent( QTimerEvent * ) +{ + connectionClosed(); +} + + +ServerDTP::ServerDTP( QObject *parent = 0, const char* name = 0) + : QSocket( parent, name ), mode( Idle ), createTargzProc( 0 ), +retrieveTargzProc( 0 ), gzipProc( 0 ) +{ + + connect( this, SIGNAL( connected() ), SLOT( connected() ) ); + connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); + connect( this, SIGNAL( bytesWritten( int ) ), SLOT( bytesWritten( int ) ) ); + connect( this, SIGNAL( readyRead() ), SLOT( readyRead() ) ); + + gzipProc = new QProcess( this, "gzipProc" ); + gzipProc->setCommunication( QProcess::Stdin | QProcess::Stdout ); + + createTargzProc = new QProcess( QString("tar"), this, "createTargzProc"); + createTargzProc->setCommunication( QProcess::Stdout ); + createTargzProc->setWorkingDirectory( QDir::rootDirPath() ); + connect( createTargzProc, SIGNAL( processExited() ), SLOT( targzDone() ) ); + + QStringList args = "tar"; + args += "-xv"; + retrieveTargzProc = new QProcess( args, this, "retrieveTargzProc" ); + retrieveTargzProc->setCommunication( QProcess::Stdin ); + retrieveTargzProc->setWorkingDirectory( QDir::rootDirPath() ); + connect( retrieveTargzProc, SIGNAL( processExited() ), + SIGNAL( completed() ) ); + connect( retrieveTargzProc, SIGNAL( processExited() ), + SLOT( extractTarDone() ) ); +} + +ServerDTP::~ServerDTP() +{ + buf.close(); + file.close(); + createTargzProc->kill(); +} + +void ServerDTP::extractTarDone() +{ + qDebug("extract done"); + QCopEnvelope e( "QPE/Desktop", "restoreDone(QString)" ); + e << file.name(); +} + +void ServerDTP::connected() +{ + // send file mode + switch ( mode ) { + case SendFile : + if ( !file.exists() || !file.open( IO_ReadOnly) ) { + emit failed(); + mode = Idle; + return; + } + + //qDebug( "Debug: Sending file '%s'", file.name().latin1() ); + + bytes_written = 0; + if ( file.size() == 0 ) { + //make sure it doesn't hang on empty files + file.close(); + emit completed(); + mode = Idle; + } else { + + if( !file.atEnd() ) { + QCString s; + s.resize( block_size ); + int bytes = file.readBlock( s.data(), block_size ); + writeBlock( s.data(), bytes ); + } + } + break; + case SendGzipFile: + if ( createTargzProc->isRunning() ) { + // SHOULDN'T GET HERE, BUT DOING A SAFETY CHECK ANYWAY + qWarning("Previous tar --gzip process is still running; killing it..."); + createTargzProc->kill(); + } + + bytes_written = 0; + qDebug("==>start send tar process"); + if ( !createTargzProc->start() ) + qWarning("Error starting %s or %s", + createTargzProc->arguments().join(" ").latin1(), + gzipProc->arguments().join(" ").latin1() ); + break; + case SendBuffer: + if ( !buf.open( IO_ReadOnly) ) { + emit failed(); + mode = Idle; + return; + } + + // qDebug( "Debug: Sending byte array" ); + bytes_written = 0; + while( !buf.atEnd() ) + putch( buf.getch() ); + buf.close(); + break; + case RetrieveFile: + // retrieve file mode + if ( file.exists() && !file.remove() ) { + emit failed(); + mode = Idle; + return; + } + + if ( !file.open( IO_WriteOnly) ) { + emit failed(); + mode = Idle; + return; + } + // qDebug( "Debug: Retrieving file %s", file.name().latin1() ); + break; + case RetrieveGzipFile: + qDebug("=-> starting tar process to receive .tgz file"); + break; + case RetrieveBuffer: + // retrieve buffer mode + if ( !buf.open( IO_WriteOnly) ) { + emit failed(); + mode = Idle; + return; + } + // qDebug( "Debug: Retrieving byte array" ); + break; + case Idle: + qDebug("connection established but mode set to Idle; BUG!"); + break; + } +} + +void ServerDTP::connectionClosed() +{ + //qDebug( "Debug: Data connection closed %ld bytes written", bytes_written ); + + // send file mode + if ( SendFile == mode ) { + if ( bytes_written == file.size() ) + emit completed(); + else + emit failed(); + } + + // send buffer mode + else if ( SendBuffer == mode ) { + if ( bytes_written == buf.size() ) + emit completed(); + else + emit failed(); + } + + // retrieve file mode + else if ( RetrieveFile == mode ) { + file.close(); + emit completed(); + } + + else if ( RetrieveGzipFile == mode ) { + qDebug("Done writing ungzip file; closing input"); + gzipProc->flushStdin(); + gzipProc->closeStdin(); + } + + // retrieve buffer mode + else if ( RetrieveBuffer == mode ) { + buf.close(); + emit completed(); + } + + mode = Idle; +} + +void ServerDTP::bytesWritten( int bytes ) +{ + bytes_written += bytes; + + // send file mode + if ( SendFile == mode ) { + + if ( bytes_written == file.size() ) { + // qDebug( "Debug: Sending complete: %d bytes", file.size() ); + file.close(); + emit completed(); + mode = Idle; + } + else if( !file.atEnd() ) { + QCString s; + s.resize( block_size ); + int bytes = file.readBlock( s.data(), block_size ); + writeBlock( s.data(), bytes ); + } + } + + // send buffer mode + if ( SendBuffer == mode ) { + + if ( bytes_written == buf.size() ) { + // qDebug( "Debug: Sending complete: %d bytes", buf.size() ); + emit completed(); + mode = Idle; + } + } +} + +void ServerDTP::readyRead() +{ + // retrieve file mode + if ( RetrieveFile == mode ) { + QCString s; + s.resize( bytesAvailable() ); + readBlock( s.data(), bytesAvailable() ); + file.writeBlock( s.data(), s.size() ); + } + else if ( RetrieveGzipFile == mode ) { + if ( !gzipProc->isRunning() ) + gzipProc->start(); + + QByteArray s; + s.resize( bytesAvailable() ); + readBlock( s.data(), bytesAvailable() ); + gzipProc->writeToStdin( s ); + qDebug("wrote %d bytes to ungzip ", s.size() ); + } + // retrieve buffer mode + else if ( RetrieveBuffer == mode ) { + QCString s; + s.resize( bytesAvailable() ); + readBlock( s.data(), bytesAvailable() ); + buf.writeBlock( s.data(), s.size() ); + } +} + +void ServerDTP::writeTargzBlock() +{ + QByteArray block = gzipProc->readStdout(); + writeBlock( block.data(), block.size() ); + qDebug("writeTargzBlock %d", block.size()); + if ( !createTargzProc->isRunning() ) { + qDebug("tar and gzip done"); + emit completed(); + mode = Idle; + disconnect( gzipProc, SIGNAL( readyReadStdout() ), + this, SLOT( writeTargzBlock() ) ); + } +} + +void ServerDTP::targzDone() +{ + //qDebug("targz done"); + disconnect( createTargzProc, SIGNAL( readyReadStdout() ), + this, SLOT( gzipTarBlock() ) ); + gzipProc->closeStdin(); +} + +void ServerDTP::gzipTarBlock() +{ + //qDebug("gzipTarBlock"); + if ( !gzipProc->isRunning() ) { + //qDebug("auto start gzip proc"); + gzipProc->start(); + } + gzipProc->writeToStdin( createTargzProc->readStdout() ); +} + +void ServerDTP::sendFile( const QString fn, const QHostAddress& host, Q_UINT16 port ) +{ + file.setName( fn ); + mode = SendFile; + connectToHost( host.toString(), port ); +} + +void ServerDTP::sendFile( const QString fn ) +{ + file.setName( fn ); + mode = SendFile; +} + +void ServerDTP::sendGzipFile( const QString &fn, + const QStringList &archiveTargets, + const QHostAddress& host, Q_UINT16 port ) +{ + sendGzipFile( fn, archiveTargets ); + connectToHost( host.toString(), port ); +} + +void ServerDTP::sendGzipFile( const QString &fn, + const QStringList &archiveTargets ) +{ + mode = SendGzipFile; + file.setName( fn ); + + QStringList args = "tar"; + args += "-cv"; + args += archiveTargets; + qDebug("sendGzipFile %s", args.join(" ").latin1() ); + createTargzProc->setArguments( args ); + connect( createTargzProc, + SIGNAL( readyReadStdout() ), SLOT( gzipTarBlock() ) ); + + gzipProc->setArguments( "gzip" ); + connect( gzipProc, SIGNAL( readyReadStdout() ), + SLOT( writeTargzBlock() ) ); +} + +void ServerDTP::gunzipDone() +{ + qDebug("gunzipDone"); + disconnect( gzipProc, SIGNAL( processExited() ), + this, SLOT( gunzipDone() ) ); + retrieveTargzProc->closeStdin(); + disconnect( gzipProc, SIGNAL( readyReadStdout() ), + this, SLOT( tarExtractBlock() ) ); +} + +void ServerDTP::tarExtractBlock() +{ + qDebug("ungzipTarBlock"); + if ( !retrieveTargzProc->isRunning() ) { + qDebug("auto start ungzip proc"); + if ( !retrieveTargzProc->start() ) + qWarning(" failed to start tar -x process"); + } + retrieveTargzProc->writeToStdin( gzipProc->readStdout() ); +} + + +void ServerDTP::retrieveFile( const QString fn, const QHostAddress& host, Q_UINT16 port ) +{ + file.setName( fn ); + mode = RetrieveFile; + connectToHost( host.toString(), port ); +} + +void ServerDTP::retrieveFile( const QString fn ) +{ + file.setName( fn ); + mode = RetrieveFile; +} + +void ServerDTP::retrieveGzipFile( const QString &fn ) +{ + qDebug("retrieveGzipFile %s", fn.latin1()); + file.setName( fn ); + mode = RetrieveGzipFile; + + gzipProc->setArguments( "gunzip" ); + connect( gzipProc, SIGNAL( readyReadStdout() ), + SLOT( tarExtractBlock() ) ); + connect( gzipProc, SIGNAL( processExited() ), + SLOT( gunzipDone() ) ); +} + +void ServerDTP::retrieveGzipFile( const QString &fn, const QHostAddress& host, Q_UINT16 port ) +{ + retrieveGzipFile( fn ); + connectToHost( host.toString(), port ); +} + +void ServerDTP::sendByteArray( const QByteArray& array, const QHostAddress& host, Q_UINT16 port ) +{ + buf.setBuffer( array ); + mode = SendBuffer; + connectToHost( host.toString(), port ); +} + +void ServerDTP::sendByteArray( const QByteArray& array ) +{ + buf.setBuffer( array ); + mode = SendBuffer; +} + +void ServerDTP::retrieveByteArray( const QHostAddress& host, Q_UINT16 port ) +{ + buf.setBuffer( QByteArray() ); + mode = RetrieveBuffer; + connectToHost( host.toString(), port ); +} + +void ServerDTP::retrieveByteArray() +{ + buf.setBuffer( QByteArray() ); + mode = RetrieveBuffer; +} + +void ServerDTP::setSocket( int socket ) +{ + QSocket::setSocket( socket ); + connected(); +} + diff --git a/core/launcher/transferserver.h b/core/launcher/transferserver.h new file mode 100644 index 0000000..076e460 --- a/dev/null +++ b/core/launcher/transferserver.h @@ -0,0 +1,168 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#include +#include +#include +#include + +class QFileInfo; +class QProcess; +class TransferServer : public QServerSocket +{ + Q_OBJECT + +public: + TransferServer( Q_UINT16 port, QObject *parent = 0, const char* name = 0 ); + virtual ~TransferServer(); + + void newConnection( int socket ); +}; + + +class ServerDTP : public QSocket +{ + Q_OBJECT + +public: + ServerDTP( QObject *parent = 0, const char* name = 0 ); + ~ServerDTP(); + + enum Mode{ Idle = 0, SendFile, SendGzipFile, SendBuffer, + RetrieveFile, RetrieveGzipFile, RetrieveBuffer }; + + void sendFile( const QString fn ); + void sendFile( const QString fn, const QHostAddress& host, Q_UINT16 port ); + void sendGzipFile( const QString &fn, const QStringList &archiveTargets ); + void sendGzipFile( const QString &fn, const QStringList &archiveTargets, + const QHostAddress& host, Q_UINT16 port ); + void sendByteArray( const QByteArray& array ); + void sendByteArray( const QByteArray& array, const QHostAddress& host, Q_UINT16 port ); + + void retrieveFile( const QString fn ); + void retrieveFile( const QString fn, const QHostAddress& host, Q_UINT16 port ); + void retrieveGzipFile( const QString &fn ); + void retrieveGzipFile( const QString &fn, const QHostAddress& host, Q_UINT16 port ); + void retrieveByteArray(); + void retrieveByteArray( const QHostAddress& host, Q_UINT16 port ); + + Mode dtpMode() { return mode; } + QByteArray buffer() { return buf.buffer(); } + + void setSocket( int socket ); + +signals: + void completed(); + void failed(); + +private slots: + void connectionClosed(); + void connected(); + void bytesWritten( int bytes ); + void readyRead(); + void writeTargzBlock(); + void targzDone(); + + void gzipTarBlock(); + void tarExtractBlock(); + void gunzipDone(); + void extractTarDone(); + +private: + + unsigned long bytes_written; + Mode mode; + QFile file; + QBuffer buf; + QProcess *createTargzProc; + QProcess *retrieveTargzProc; + QProcess *gzipProc; +}; + +class ServerSocket : public QServerSocket +{ + Q_OBJECT + +public: + ServerSocket( Q_UINT16 port, QObject *parent = 0, const char* name = 0 ) + : QServerSocket( port, 1, parent, name ) {} + + void newConnection( int socket ) { emit newIncomming( socket ); } +signals: + void newIncomming( int socket ); +}; + +class ServerPI : public QSocket +{ + Q_OBJECT + + enum State { Connected, Wait_USER, Wait_PASS, Ready, Forbidden }; + enum Transfer { SendFile = 0, RetrieveFile = 1, SendByteArray = 2, RetrieveByteArray = 3 }; + +public: + ServerPI( int socket, QObject *parent = 0, const char* name = 0 ); + virtual ~ServerPI(); + +protected slots: + void read(); + void send( const QString& msg ); + void process( const QString& command ); + void connectionClosed(); + void dtpCompleted(); + void dtpFailed(); + void dtpError( int ); + void newConnection( int socket ); + +protected: + bool checkUser( const QString& user ); + bool checkPassword( const QString& pw ); + bool checkReadFile( const QString& file ); + bool checkWriteFile( const QString& file ); + bool parsePort( const QString& pw ); + bool backupRestoreGzip( const QString &file, QStringList &targets ); + bool backupRestoreGzip( const QString &file ); + + bool sendList( const QString& arg ); + void sendFile( const QString& file ); + void retrieveFile( const QString& file ); + + QString permissionString( QFileInfo *info ); + QString fileListing( QFileInfo *info ); + QString absFilePath( const QString& file ); + + void timerEvent( QTimerEvent *e ); + +private: + State state; + Q_UINT16 peerport; + QHostAddress peeraddress; + bool passiv; + bool wait[4]; + ServerDTP *dtp; + ServerSocket *serversocket; + QString waitfile; + QDir directory; + QByteArray waitarray; + QString renameFrom; + QString lastCommand; + int waitsocket; +}; + +bool accessAuthorized(QHostAddress peeraddress); diff --git a/core/launcher/wait.cpp b/core/launcher/wait.cpp new file mode 100644 index 0000000..059e6f1 --- a/dev/null +++ b/core/launcher/wait.cpp @@ -0,0 +1,64 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "wait.h" + +#include + +#include +#include +#include + + +Wait *lastWaitObject = NULL; + + +Wait::Wait( QWidget *parent ) : QWidget( parent ), + pm( Resource::loadPixmap( "wait" ) ), waiting( FALSE ) +{ + setFixedSize( pm.size() ); + lastWaitObject = this; + hide(); +} + + +Wait *Wait::getWaitObject() +{ + return lastWaitObject; +} + + +void Wait::setWaiting( bool w ) +{ + waiting = w; + if ( w ) + show(); + else + hide(); +} + + +void Wait::paintEvent( QPaintEvent * ) +{ + QPainter p( this ); + p.drawPixmap( 0, 0, pm ); +} + + diff --git a/core/launcher/wait.h b/core/launcher/wait.h new file mode 100644 index 0000000..519b654 --- a/dev/null +++ b/core/launcher/wait.h @@ -0,0 +1,45 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef __WAIT_H__ +#define __WAIT_H__ + +#include + +#include +#include +#include + + +class Wait : public QWidget +{ +public: + Wait( QWidget *parent ); + void setWaiting( bool w ); + void paintEvent( QPaintEvent * ); + static Wait *getWaitObject(); +private: + QPixmap pm; + bool waiting; +}; + + +#endif // __WAIT_H__ + diff --git a/core/multimedia/opieplayer/.cvsignore b/core/multimedia/opieplayer/.cvsignore new file mode 100644 index 0000000..6fe2396 --- a/dev/null +++ b/core/multimedia/opieplayer/.cvsignore @@ -0,0 +1,2 @@ +moc_* +Makefile diff --git a/core/multimedia/opieplayer/Makefile.in b/core/multimedia/opieplayer/Makefile.in new file mode 100644 index 0000000..5fca66e --- a/dev/null +++ b/core/multimedia/opieplayer/Makefile.in @@ -0,0 +1,280 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) -DQCONFIG=\"qpe\" +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) -DQCONFIG=\"qpe\" +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe -lpthread $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = $(QPEDIR)/bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = mpegplayer +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = loopcontrol.h \ + mediaplayerplugininterface.h \ + playlistselection.h \ + mediaplayerstate.h \ + videowidget.h \ + audiowidget.h \ + playlistwidget.h \ + mediaplayer.h \ + audiodevice.h +SOURCES = main.cpp \ + loopcontrol.cpp \ + playlistselection.cpp \ + mediaplayerstate.cpp \ + videowidget.cpp \ + audiowidget.cpp \ + playlistwidget.cpp \ + mediaplayer.cpp \ + audiodevice.cpp +OBJECTS = main.o \ + loopcontrol.o \ + playlistselection.o \ + mediaplayerstate.o \ + videowidget.o \ + audiowidget.o \ + playlistwidget.o \ + mediaplayer.o \ + audiodevice.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = moc_loopcontrol.cpp \ + moc_playlistselection.cpp \ + moc_mediaplayerstate.cpp \ + moc_videowidget.cpp \ + moc_audiowidget.cpp \ + moc_playlistwidget.cpp \ + moc_mediaplayer.cpp \ + moc_audiodevice.cpp +OBJMOC = moc_loopcontrol.o \ + moc_playlistselection.o \ + moc_mediaplayerstate.o \ + moc_videowidget.o \ + moc_audiowidget.o \ + moc_playlistwidget.o \ + moc_mediaplayer.o \ + moc_audiodevice.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake mpegplayer.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +main.o: main.cpp \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + mediaplayerstate.h \ + playlistwidget.h \ + $(QPEDIR)/include/qpe/applnk.h \ + audiowidget.h \ + videowidget.h \ + loopcontrol.h \ + mediaplayer.h \ + $(QPEDIR)/include/qpe/qlibrary.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h \ + mediaplayerplugininterface.h + +loopcontrol.o: loopcontrol.cpp \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h \ + loopcontrol.h \ + videowidget.h \ + audiodevice.h \ + mediaplayerplugininterface.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h \ + mediaplayerstate.h + +playlistselection.o: playlistselection.cpp \ + $(QPEDIR)/include/qpe/applnk.h \ + $(QPEDIR)/include/qpe/resource.h \ + playlistselection.h + +mediaplayerstate.o: mediaplayerstate.cpp \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/qlibrary.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h \ + $(QPEDIR)/include/qpe/config.h \ + mediaplayerplugininterface.h \ + mediaplayerstate.h \ + libmad/libmadpluginimpl.h \ + libmpeg3/libmpeg3pluginimpl.h \ + wavplugin/wavpluginimpl.h + +videowidget.o: videowidget.cpp \ + $(QPEDIR)/include/qpe/resource.h \ + videowidget.h \ + mediaplayerplugininterface.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h \ + mediaplayerstate.h + +audiowidget.o: audiowidget.cpp \ + $(QPEDIR)/include/qpe/resource.h \ + audiowidget.h \ + mediaplayerstate.h + +playlistwidget.o: playlistwidget.cpp \ + $(QPEDIR)/include/qpe/qpemenubar.h \ + $(QPEDIR)/include/qpe/qpetoolbar.h \ + $(QPEDIR)/include/qpe/fileselector.h \ + $(QPEDIR)/include/qpe/applnk.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/global.h \ + $(QPEDIR)/include/qpe/resource.h \ + playlistselection.h \ + playlistwidget.h \ + mediaplayerstate.h + +mediaplayer.o: mediaplayer.cpp \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/qlibrary.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/config.h \ + mediaplayer.h \ + mediaplayerplugininterface.h \ + playlistwidget.h \ + $(QPEDIR)/include/qpe/applnk.h \ + audiowidget.h \ + loopcontrol.h \ + audiodevice.h \ + mediaplayerstate.h + +audiodevice.o: audiodevice.cpp \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/config.h \ + audiodevice.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h + +moc_loopcontrol.o: moc_loopcontrol.cpp \ + loopcontrol.h + +moc_playlistselection.o: moc_playlistselection.cpp \ + playlistselection.h \ + $(QPEDIR)/include/qpe/applnk.h + +moc_mediaplayerstate.o: moc_mediaplayerstate.cpp \ + mediaplayerstate.h + +moc_videowidget.o: moc_videowidget.cpp \ + videowidget.h + +moc_audiowidget.o: moc_audiowidget.cpp \ + audiowidget.h + +moc_playlistwidget.o: moc_playlistwidget.cpp \ + playlistwidget.h \ + $(QPEDIR)/include/qpe/applnk.h + +moc_mediaplayer.o: moc_mediaplayer.cpp \ + mediaplayer.h \ + $(QPEDIR)/include/qpe/qlibrary.h \ + $(QPEDIR)/include/qpe/qcom.h \ + $(QPEDIR)/include/qpe/quuid.h \ + mediaplayerplugininterface.h + +moc_audiodevice.o: moc_audiodevice.cpp \ + audiodevice.h + +moc_loopcontrol.cpp: loopcontrol.h + $(MOC) loopcontrol.h -o moc_loopcontrol.cpp + +moc_playlistselection.cpp: playlistselection.h + $(MOC) playlistselection.h -o moc_playlistselection.cpp + +moc_mediaplayerstate.cpp: mediaplayerstate.h + $(MOC) mediaplayerstate.h -o moc_mediaplayerstate.cpp + +moc_videowidget.cpp: videowidget.h + $(MOC) videowidget.h -o moc_videowidget.cpp + +moc_audiowidget.cpp: audiowidget.h + $(MOC) audiowidget.h -o moc_audiowidget.cpp + +moc_playlistwidget.cpp: playlistwidget.h + $(MOC) playlistwidget.h -o moc_playlistwidget.cpp + +moc_mediaplayer.cpp: mediaplayer.h + $(MOC) mediaplayer.h -o moc_mediaplayer.cpp + +moc_audiodevice.cpp: audiodevice.h + $(MOC) audiodevice.h -o moc_audiodevice.cpp + + diff --git a/core/multimedia/opieplayer/audiodevice.cpp b/core/multimedia/opieplayer/audiodevice.cpp new file mode 100644 index 0000000..8861015 --- a/dev/null +++ b/core/multimedia/opieplayer/audiodevice.cpp @@ -0,0 +1,386 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#include +#include +#include "audiodevice.h" + +#if ( defined Q_WS_QWS || defined(_WS_QWS_) ) && !defined(QT_NO_COP) +#include "qpe/qcopenvelope_qws.h" +#endif + +#ifdef Q_WS_WIN +#include +#include +#include +#endif + +#if defined(Q_WS_X11) || defined(Q_WS_QWS) +#include +#include +#include +#include +#include +#include +#include +#endif + +#if defined(Q_OS_WIN32) +static const int expectedBytesPerMilliSecond = 2 * 2 * 44000 / 1000; +static const int timerResolutionMilliSeconds = 30; +static const int sound_fragment_bytes = timerResolutionMilliSeconds * expectedBytesPerMilliSecond; +#else +# if defined(QT_QWS_IPAQ) +static const int sound_fragment_shift = 14; +# else +static const int sound_fragment_shift = 16; +# endif +static const int sound_fragment_bytes = (1<> 16; +#else + int mixerHandle = open( "/dev/mixer", O_RDWR ); + if ( mixerHandle >= 0 ) { + ioctl( mixerHandle, MIXER_READ(0), &volume ); + close( mixerHandle ); + } else + qDebug( "get volume of audio device failed" ); + leftVolume = ((volume & 0x00FF) << 16) / 101; + rightVolume = ((volume & 0xFF00) << 8) / 101; +#endif +} + + +void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume, bool muted ) { + AudioDevicePrivate::muted = muted; + if ( muted ) { + AudioDevicePrivate::leftVolume = leftVolume; + AudioDevicePrivate::rightVolume = rightVolume; + leftVolume = 0; + rightVolume = 0; + } else { + leftVolume = ( (int) leftVolume < 0 ) ? 0 : (( leftVolume > 0xFFFF ) ? 0xFFFF : leftVolume ); + rightVolume = ( (int)rightVolume < 0 ) ? 0 : (( rightVolume > 0xFFFF ) ? 0xFFFF : rightVolume ); + } +#ifdef Q_OS_WIN32 + HWAVEOUT handle; + WAVEFORMATEX formatData; + formatData.cbSize = sizeof(WAVEFORMATEX); + formatData.wFormatTag = WAVE_FORMAT_PCM; + formatData.nAvgBytesPerSec = 4 * 44000; + formatData.nBlockAlign = 4; + formatData.nChannels = 2; + formatData.nSamplesPerSec = 44000; + formatData.wBitsPerSample = 16; + waveOutOpen(&handle, WAVE_MAPPER, &formatData, 0L, 0L, CALLBACK_NULL); + unsigned int volume = (rightVolume << 16) | leftVolume; + if ( waveOutSetVolume( handle, volume ) ) + qDebug( "set volume of audio device failed" ); + waveOutClose( handle ); +#else + // Volume can be from 0 to 100 which is 101 distinct values + unsigned int rV = (rightVolume * 101) >> 16; + +# if 0 + unsigned int lV = (leftVolume * 101) >> 16; + unsigned int volume = ((rV << 8) & 0xFF00) | (lV & 0x00FF); + int mixerHandle = 0; + if ( ( mixerHandle = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { + ioctl( mixerHandle, MIXER_WRITE(0), &volume ); + close( mixerHandle ); + } else + qDebug( "set volume of audio device failed" ); +# else + // This is the way this has to be done now I guess, doesn't allow for + // independant right and left channel setting, or setting for different outputs + Config cfg("Sound"); + cfg.setGroup("System"); + cfg.writeEntry("Volume",(int)rV); +# endif + +#endif +// qDebug( "setting volume to: 0x%x", volume ); +#if ( defined Q_WS_QWS || defined(_WS_QWS_) ) && !defined(QT_NO_COP) + // Send notification that the volume has changed + QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << muted; +#endif +} + + + + +AudioDevice::AudioDevice( unsigned int f, unsigned int chs, unsigned int bps ) { + d = new AudioDevicePrivate; + d->frequency = f; + d->channels = chs; + d->bytesPerSample = bps; + + connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( volumeChanged(bool) ) ); + +#ifdef Q_OS_WIN32 + UINT result; + WAVEFORMATEX formatData; + formatData.cbSize = sizeof(WAVEFORMATEX); +/* + // Other possible formats windows supports + formatData.wFormatTag = WAVE_FORMAT_MPEG; + formatData.wFormatTag = WAVE_FORMAT_MPEGLAYER3; + formatData.wFormatTag = WAVE_FORMAT_ADPCM; +*/ + formatData.wFormatTag = WAVE_FORMAT_PCM; + formatData.nAvgBytesPerSec = bps * chs * f; + formatData.nBlockAlign = bps * chs; + formatData.nChannels = chs; + formatData.nSamplesPerSec = f; + formatData.wBitsPerSample = bps * 8; + // Open a waveform device for output + if (result = waveOutOpen((LPHWAVEOUT)&d->handle, WAVE_MAPPER, &formatData, 0L, 0L, CALLBACK_NULL)) { + QString errorMsg = "error opening audio device.\nReason: %i - "; + switch (result) { + case MMSYSERR_ALLOCATED: errorMsg += "Specified resource is already allocated."; break; + case MMSYSERR_BADDEVICEID: errorMsg += "Specified device identifier is out of range."; break; + case MMSYSERR_NODRIVER: errorMsg += "No device driver is present."; break; + case MMSYSERR_NOMEM: errorMsg += "Unable to allocate or lock memory."; break; + case WAVERR_BADFORMAT: errorMsg += "Attempted to open with an unsupported waveform-audio format."; break; + case WAVERR_SYNC: errorMsg += "The device is synchronous but waveOutOpen was called without using the WAVE_ALLOWSYNC flag."; break; + default: errorMsg += "Undefined error"; break; + } + qDebug( errorMsg, result ); + } + + d->bufferSize = sound_fragment_bytes; +#else + + int fragments = 0x10000 * 8 + sound_fragment_shift; + int format = AFMT_S16_LE; + int capabilities = 0; + +#ifdef KEEP_DEVICE_OPEN + if ( AudioDevicePrivate::dspFd == 0 ) { +#endif + if ( ( d->handle = ::open( "/dev/dsp", O_WRONLY ) ) < 0 ) { + qDebug( "error opening audio device /dev/dsp, sending data to /dev/null instead" ); + d->handle = ::open( "/dev/null", O_WRONLY ); + } +#ifdef KEEP_DEVICE_OPEN + AudioDevicePrivate::dspFd = d->handle; + } else { + d->handle = AudioDevicePrivate::dspFd; + } +#endif + + ioctl( d->handle, SNDCTL_DSP_GETCAPS, &capabilities ); + ioctl( d->handle, SNDCTL_DSP_SETFRAGMENT, &fragments ); + ioctl( d->handle, SNDCTL_DSP_SETFMT, &format ); + ioctl( d->handle, SNDCTL_DSP_SPEED, &d->frequency ); + if ( ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels ) == -1 ) { + d->channels = ( d->channels == 1 ) ? 2 : d->channels; + ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels ); + } + + d->bufferSize = sound_fragment_bytes; + d->unwrittenBuffer = new char[d->bufferSize]; + d->unwritten = 0; + d->can_GETOSPACE = TRUE; // until we find otherwise + + //if ( chs != d->channels ) qDebug( "Wanted %d, got %d channels", chs, d->channels ); + //if ( f != d->frequency ) qDebug( "wanted %dHz, got %dHz", f, d->frequency ); + //if ( capabilities & DSP_CAP_BATCH ) qDebug( "Sound card has local buffer" ); + //if ( capabilities & DSP_CAP_REALTIME )qDebug( "Sound card has realtime sync" ); + //if ( capabilities & DSP_CAP_TRIGGER ) qDebug( "Sound card has precise trigger" ); + //if ( capabilities & DSP_CAP_MMAP ) qDebug( "Sound card can mmap" ); +#endif +} + + +AudioDevice::~AudioDevice() { +#ifdef Q_OS_WIN32 + waveOutClose( (HWAVEOUT)d->handle ); +#else +# ifndef KEEP_DEVICE_OPEN + close( d->handle ); // Now it should be safe to shut the handle +# endif + delete d->unwrittenBuffer; + delete d; +#endif +} + + +void AudioDevice::volumeChanged( bool muted ) +{ + AudioDevicePrivate::muted = muted; +} + + +void AudioDevice::write( char *buffer, unsigned int length ) +{ +#ifdef Q_OS_WIN32 + // returns immediately and (to be implemented) emits completedIO() when finished writing + WAVEHDR *lpWaveHdr = (WAVEHDR *)malloc( sizeof(WAVEHDR) ); + // maybe the buffer should be copied so that this fool proof, but its a performance hit + lpWaveHdr->lpData = buffer; + lpWaveHdr->dwBufferLength = length; + lpWaveHdr->dwFlags = 0L; + lpWaveHdr->dwLoops = 0L; + waveOutPrepareHeader( (HWAVEOUT)d->handle, lpWaveHdr, sizeof(WAVEHDR) ); + // waveOutWrite returns immediately. the data is sent in the background. + if ( waveOutWrite( (HWAVEOUT)d->handle, lpWaveHdr, sizeof(WAVEHDR) ) ) + qDebug( "failed to write block to audio device" ); + // emit completedIO(); +#else + int t = ::write( d->handle, buffer, length ); + if ( t<0 ) t = 0; + if ( t != (int)length) { + qDebug("Ahhh!! memcpys 1"); + memcpy(d->unwrittenBuffer,buffer+t,length-t); + d->unwritten = length-t; + } +#endif +} + + +unsigned int AudioDevice::channels() const +{ + return d->channels; +} + + +unsigned int AudioDevice::frequency() const +{ + return d->frequency; +} + + +unsigned int AudioDevice::bytesPerSample() const +{ + return d->bytesPerSample; +} + + +unsigned int AudioDevice::bufferSize() const +{ + return d->bufferSize; +} + +unsigned int AudioDevice::canWrite() const +{ +#ifdef Q_OS_WIN32 + return bufferSize(); // Any better? +#else + audio_buf_info info; + if ( d->can_GETOSPACE && ioctl(d->handle,SNDCTL_DSP_GETOSPACE,&info) ) { + d->can_GETOSPACE = FALSE; + fcntl( d->handle, F_SETFL, O_NONBLOCK ); + } + if ( d->can_GETOSPACE ) { + int t = info.fragments * sound_fragment_bytes; + return QMIN(t,(int)bufferSize()); + } else { + if ( d->unwritten ) { + int t = ::write( d->handle, d->unwrittenBuffer, d->unwritten ); + if ( t<0 ) t = 0; + if ( (unsigned)t!=d->unwritten ) { + memcpy(d->unwrittenBuffer,d->unwrittenBuffer+t,d->unwritten-t); + d->unwritten -= t; + } else { + d->unwritten = 0; + } + } + if ( d->unwritten ) + return 0; + else + return d->bufferSize; + } +#endif +} + + +int AudioDevice::bytesWritten() { +#ifdef Q_OS_WIN32 + MMTIME pmmt = { TIME_BYTES, 0 }; + if ( ( waveOutGetPosition( (HWAVEOUT)d->handle, &pmmt, sizeof(MMTIME) ) != MMSYSERR_NOERROR ) || ( pmmt.wType != TIME_BYTES ) ) { + qDebug( "failed to get audio device position" ); + return -1; + } + return pmmt.u.cb; +#else + int buffered = 0; + if ( ioctl( d->handle, SNDCTL_DSP_GETODELAY, &buffered ) ) { + qDebug( "failed to get audio device position" ); + return -1; + } + return buffered; +#endif +} + diff --git a/core/multimedia/opieplayer/audiodevice.h b/core/multimedia/opieplayer/audiodevice.h new file mode 100644 index 0000000..928f134 --- a/dev/null +++ b/core/multimedia/opieplayer/audiodevice.h @@ -0,0 +1,71 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef AUDIODEVICE_H +#define AUDIODEVICE_H + + +#include + + +class AudioDevicePrivate; + + +class AudioDevice : public QObject { + Q_OBJECT +public: + AudioDevice( unsigned int freq = 44000, unsigned int channels = 2, unsigned int bytesPerSample = 2 ); + ~AudioDevice(); + + unsigned int canWrite() const; + void write( char *buffer, unsigned int length ); + int bytesWritten(); + + unsigned int channels() const; + unsigned int frequency() const; + unsigned int bytesPerSample() const; + unsigned int bufferSize() const; + + // Each volume level is from 0 to 0xFFFF + static void getVolume( unsigned int& left, unsigned int& right, bool& muted ); + static void setVolume( unsigned int left, unsigned int right, bool muted ); + + static unsigned int leftVolume() { bool muted; unsigned int l, r; getVolume( l, r, muted ); return l; } + static unsigned int rightVolume() { bool muted; unsigned int l, r; getVolume( l, r, muted ); return r; } + static bool isMuted() { bool muted; unsigned int l, r; getVolume( l, r, muted ); return muted; } + + static void increaseVolume() { setVolume( leftVolume() + 1968, rightVolume() + 1968, isMuted() ); } + static void decreaseVolume() { setVolume( leftVolume() - 1966, rightVolume() - 1966, isMuted() ); } + +public slots: + // Convinence functions derived from above functions + void setVolume( unsigned int level ) { setVolume( level, level, isMuted() ); } + void mute() { setVolume( leftVolume(), rightVolume(), TRUE ); } + void volumeChanged( bool muted ); + +signals: + void completedIO(); + +private: + AudioDevicePrivate *d; +}; + + +#endif // AUDIODEVICE_H + diff --git a/core/multimedia/opieplayer/audiowidget.cpp b/core/multimedia/opieplayer/audiowidget.cpp new file mode 100644 index 0000000..243c58c --- a/dev/null +++ b/core/multimedia/opieplayer/audiowidget.cpp @@ -0,0 +1,277 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#include +#include +#include +#include +#include +#include "audiowidget.h" +#include "mediaplayerstate.h" + + +extern MediaPlayerState *mediaPlayerState; + + +static const int xo = -2; // movable x offset +static const int yo = 22; // movable y offset + + +struct MediaButton { + int xPos, yPos; + int color; + bool isToggle, isBig, isHeld, isDown; +}; + + +// Layout information for the audioButtons (and if it is a toggle button or not) +MediaButton audioButtons[] = { + { 3*30-15+xo, 3*30-13+yo, 0, TRUE, TRUE, FALSE, FALSE }, // play + { 1*30+xo, 5*30+yo, 2, FALSE, FALSE, FALSE, FALSE }, // stop + { 5*30+xo, 5*30+yo, 2, TRUE, FALSE, FALSE, FALSE }, // pause + { 6*30-5+xo, 3*30+yo, 1, FALSE, FALSE, FALSE, FALSE }, // next + { 0*30+5+xo, 3*30+yo, 1, FALSE, FALSE, FALSE, FALSE }, // previous + { 3*30+xo, 0*30+5+yo, 3, FALSE, FALSE, FALSE, FALSE }, // volume up + { 3*30+xo, 6*30-5+yo, 3, FALSE, FALSE, FALSE, FALSE }, // volume down + { 5*30+xo, 1*30+yo, 0, TRUE, FALSE, FALSE, FALSE }, // repeat/loop + { 1*30+xo, 1*30+yo, 0, FALSE, FALSE, FALSE, FALSE } // playlist +}; + + +static const int numButtons = (sizeof(audioButtons)/sizeof(MediaButton)); + + +AudioWidget::AudioWidget(QWidget* parent, const char* name, WFlags f) : + QWidget( parent, name, f ) +{ + setCaption( tr("MediaPlayer") ); + setBackgroundPixmap( Resource::loadPixmap( "mpegplayer/metalFinish" ) ); + pixmaps[0] = new QPixmap( Resource::loadPixmap( "mpegplayer/mediaButtonsAll" ) ); + pixmaps[1] = new QPixmap( Resource::loadPixmap( "mpegplayer/mediaButtonsBig" ) ); + pixmaps[2] = new QPixmap( Resource::loadPixmap( "mpegplayer/mediaControls" ) ); + pixmaps[3] = new QPixmap( Resource::loadPixmap( "mpegplayer/animatedButton" ) ); + + songInfo = new Ticker( this ); + songInfo->setFocusPolicy( QWidget::NoFocus ); + songInfo->setGeometry( QRect( 7, 3, 220, 20 ) ); + + slider = new QSlider( Qt::Horizontal, this ); + slider->setFixedWidth( 220 ); + slider->setFixedHeight( 20 ); + slider->setMinValue( 0 ); + slider->setMaxValue( 1 ); + slider->setBackgroundPixmap( Resource::loadPixmap( "mpegplayer/metalFinish" ) ); + slider->setFocusPolicy( QWidget::NoFocus ); + slider->setGeometry( QRect( 7, 262, 220, 20 ) ); + + connect( slider, SIGNAL( sliderPressed() ), this, SLOT( sliderPressed() ) ); + connect( slider, SIGNAL( sliderReleased() ), this, SLOT( sliderReleased() ) ); + + connect( mediaPlayerState, SIGNAL( lengthChanged(long) ), this, SLOT( setLength(long) ) ); + connect( mediaPlayerState, SIGNAL( positionChanged(long) ),this, SLOT( setPosition(long) ) ); + connect( mediaPlayerState, SIGNAL( positionUpdated(long) ),this, SLOT( setPosition(long) ) ); + connect( mediaPlayerState, SIGNAL( viewChanged(char) ), this, SLOT( setView(char) ) ); + connect( mediaPlayerState, SIGNAL( loopingToggled(bool) ), this, SLOT( setLooping(bool) ) ); + connect( mediaPlayerState, SIGNAL( pausedToggled(bool) ), this, SLOT( setPaused(bool) ) ); + connect( mediaPlayerState, SIGNAL( playingToggled(bool) ), this, SLOT( setPlaying(bool) ) ); + + // Intialise state + setLength( mediaPlayerState->length() ); + setPosition( mediaPlayerState->position() ); + setLooping( mediaPlayerState->fullscreen() ); + setPaused( mediaPlayerState->paused() ); + setPlaying( mediaPlayerState->playing() ); + +} + + +AudioWidget::~AudioWidget() { + for ( int i = 0; i < 4; i++ ) + delete pixmaps[i]; +} + + +static bool audioSliderBeingMoved = FALSE; + + +void AudioWidget::sliderPressed() { + audioSliderBeingMoved = TRUE; +} + + +void AudioWidget::sliderReleased() { + audioSliderBeingMoved = FALSE; + if ( slider->width() == 0 ) + return; + long val = long((double)slider->value() * mediaPlayerState->length() / slider->width()); + mediaPlayerState->setPosition( val ); +} + + +void AudioWidget::setPosition( long i ) { + updateSlider( i, mediaPlayerState->length() ); +} + + +void AudioWidget::setLength( long max ) { + updateSlider( mediaPlayerState->position(), max ); +} + + +void AudioWidget::setView( char view ) { + if ( view == 'a' ) { + startTimer( 150 ); + showMaximized(); + } else { + killTimers(); + hide(); + } +} + + +void AudioWidget::updateSlider( long i, long max ) { + if ( max == 0 ) + return; + // Will flicker too much if we don't do this + // Scale to something reasonable + int width = slider->width(); + int val = int((double)i * width / max); + if ( !audioSliderBeingMoved ) { + if ( slider->value() != val ) + slider->setValue( val ); + if ( slider->maxValue() != width ) + slider->setMaxValue( width ); + } +} + + +void AudioWidget::setToggleButton( int i, bool down ) { + if ( down != audioButtons[i].isDown ) + toggleButton( i ); +} + + +void AudioWidget::toggleButton( int i ) { + audioButtons[i].isDown = !audioButtons[i].isDown; + QPainter p(this); + paintButton ( &p, i ); +} + + +void AudioWidget::paintButton( QPainter *p, int i ) { + int x = audioButtons[i].xPos; + int y = audioButtons[i].yPos; + int offset = 22 + 14 * audioButtons[i].isBig + audioButtons[i].isDown; + int buttonSize = 64 + audioButtons[i].isBig * (90 - 64); + p->drawPixmap( x, y, *pixmaps[audioButtons[i].isBig], buttonSize * (audioButtons[i].isDown + 2 * audioButtons[i].color), 0, buttonSize, buttonSize ); + p->drawPixmap( x + offset, y + offset, *pixmaps[2], 18 * i, 0, 18, 18 ); +} + + +void AudioWidget::timerEvent( QTimerEvent * ) { + static int frame = 0; + if ( !mediaPlayerState->paused() && audioButtons[ AudioPlay ].isDown ) { + frame = frame >= 7 ? 0 : frame + 1; + int x = audioButtons[AudioPlay].xPos; + int y = audioButtons[AudioPlay].yPos; + QPainter p( this ); + // Optimize to only draw the little bit of the changing images which is different + p.drawPixmap( x + 14, y + 8, *pixmaps[3], 32 * frame, 0, 32, 32 ); + p.drawPixmap( x + 37, y + 37, *pixmaps[2], 18 * AudioPlay, 0, 6, 3 ); + } +} + + +void AudioWidget::mouseMoveEvent( QMouseEvent *event ) { + for ( int i = 0; i < numButtons; i++ ) { + int size = audioButtons[i].isBig; + int x = audioButtons[i].xPos; + int y = audioButtons[i].yPos; + if ( event->state() == QMouseEvent::LeftButton ) { + // The test to see if the mouse click is inside the circular button or not + // (compared with the radius squared to avoid a square-root of our distance) + int radius = 32 + 13 * size; + QPoint center = QPoint( x + radius, y + radius ); + QPoint dXY = center - event->pos(); + int dist = dXY.x() * dXY.x() + dXY.y() * dXY.y(); + bool isOnButton = dist <= (radius * radius); +// QRect r( x, y, 64 + 22*size, 64 + 22*size ); +// bool isOnButton = r.contains( event->pos() ); // Rectangular Button code + if ( isOnButton && !audioButtons[i].isHeld ) { + audioButtons[i].isHeld = TRUE; + toggleButton(i); + switch (i) { + case AudioVolumeUp: emit moreClicked(); return; + case AudioVolumeDown: emit lessClicked(); return; + } + } else if ( !isOnButton && audioButtons[i].isHeld ) { + audioButtons[i].isHeld = FALSE; + toggleButton(i); + } + } else { + if ( audioButtons[i].isHeld ) { + audioButtons[i].isHeld = FALSE; + if ( !audioButtons[i].isToggle ) + setToggleButton( i, FALSE ); + switch (i) { + case AudioPlay: mediaPlayerState->setPlaying(audioButtons[i].isDown); return; + case AudioStop: mediaPlayerState->setPlaying(FALSE); return; + case AudioPause: mediaPlayerState->setPaused(audioButtons[i].isDown); return; + case AudioNext: mediaPlayerState->setNext(); return; + case AudioPrevious: mediaPlayerState->setPrev(); return; + case AudioLoop: mediaPlayerState->setLooping(audioButtons[i].isDown); return; + case AudioVolumeUp: emit moreReleased(); return; + case AudioVolumeDown: emit lessReleased(); return; + case AudioPlayList: mediaPlayerState->setList(); return; + } + } + } + } +} + + +void AudioWidget::mousePressEvent( QMouseEvent *event ) { + mouseMoveEvent( event ); +} + + +void AudioWidget::mouseReleaseEvent( QMouseEvent *event ) { + mouseMoveEvent( event ); +} + + +void AudioWidget::showEvent( QShowEvent* ) { + QMouseEvent event( QEvent::MouseMove, QPoint( 0, 0 ), 0, 0 ); + mouseMoveEvent( &event ); +} + + +void AudioWidget::closeEvent( QCloseEvent* ) { + mediaPlayerState->setList(); +} + + +void AudioWidget::paintEvent( QPaintEvent * ) { + QPainter p( this ); + for ( int i = 0; i < numButtons; i++ ) + paintButton( &p, i ); +} + + diff --git a/core/multimedia/opieplayer/audiowidget.h b/core/multimedia/opieplayer/audiowidget.h new file mode 100644 index 0000000..4b82a91 --- a/dev/null +++ b/core/multimedia/opieplayer/audiowidget.h @@ -0,0 +1,144 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef AUDIO_WIDGET_H +#define AUDIO_WIDGET_H + + +#include +#include +#include +#include +#include +#include +#include + + +class QPixmap; + + +enum AudioButtons { + AudioPlay, + AudioStop, + AudioPause, + AudioNext, + AudioPrevious, + AudioVolumeUp, + AudioVolumeDown, + AudioLoop, + AudioPlayList +}; + + +#define USE_DBLBUF + + +class Ticker : public QFrame { + Q_OBJECT +public: + Ticker( QWidget* parent=0 ) : QFrame( parent ) { + setFrameStyle( WinPanel | Sunken ); + setText( "No Song" ); + } + ~Ticker() { } + void setText( const QString& text ) { + pos = 0; // reset it everytime the text is changed + scrollText = text; + pixelLen = fontMetrics().width( scrollText ); + killTimers(); + if ( pixelLen > width() ) + startTimer( 50 ); + update(); + } +protected: + void timerEvent( QTimerEvent * ) { + pos = ( pos + 1 > pixelLen ) ? 0 : pos + 1; +#ifndef USE_DBLBUF + scroll( -1, 0, contentsRect() ); +#else + repaint( FALSE ); +#endif + } + void drawContents( QPainter *p ) { +#ifndef USE_DBLBUF + for ( int i = 0; i - pos < width() && (i < 1 || pixelLen > width()); i += pixelLen ) + p->drawText( i - pos, 0, INT_MAX, height(), AlignVCenter, scrollText ); +#else + // Double buffering code. + // Looks like qvfb makes it look like it flickers but I don't think it really is + QPixmap pm( width(), height() ); + pm.fill( colorGroup().base() ); + QPainter pmp( &pm ); + for ( int i = 0; i - pos < width() && (i < 1 || pixelLen > width()); i += pixelLen ) + pmp.drawText( i - pos, 0, INT_MAX, height(), AlignVCenter, scrollText ); + p->drawPixmap( 0, 0, pm ); +#endif + } +private: + QString scrollText; + int pos, pixelLen; +}; + + +class AudioWidget : public QWidget { + Q_OBJECT +public: + AudioWidget( QWidget* parent=0, const char* name=0, WFlags f=0 ); + ~AudioWidget(); + void setTickerText( const QString &text ) { songInfo->setText( text ); } + +public slots: + void updateSlider( long, long ); + void sliderPressed( ); + void sliderReleased( ); + void setPaused( bool b) { setToggleButton( AudioPause, b ); } + void setLooping( bool b) { setToggleButton( AudioLoop, b ); } + void setPlaying( bool b) { setToggleButton( AudioPlay, b ); } + void setPosition( long ); + void setLength( long ); + void setView( char ); + +signals: + void moreClicked(); + void lessClicked(); + void moreReleased(); + void lessReleased(); + void sliderMoved(long); + +protected: + void paintEvent( QPaintEvent *pe ); + void showEvent( QShowEvent *se ); + void mouseMoveEvent( QMouseEvent *event ); + void mousePressEvent( QMouseEvent *event ); + void mouseReleaseEvent( QMouseEvent *event ); + void timerEvent( QTimerEvent *event ); + void closeEvent( QCloseEvent *event ); + +private: + void toggleButton( int ); + void setToggleButton( int, bool ); + void paintButton( QPainter *p, int i ); + QPixmap *pixmaps[4]; + Ticker *songInfo; + QSlider *slider; +}; + + +#endif // AUDIO_WIDGET_H + diff --git a/core/multimedia/opieplayer/libflash/Makefile.in b/core/multimedia/opieplayer/libflash/Makefile.in new file mode 100644 index 0000000..52c8557 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/Makefile.in @@ -0,0 +1,644 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../../plugins/codecs/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = flashplugin +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = libflashplugin.h \ + libflashpluginimpl.h +SOURCES = libflashplugin.cpp \ + libflashpluginimpl.cpp \ + adpcm.cc \ + character.cc \ + flash.cc \ + graphic16.cc \ + matrix.cc \ + script.cc \ + sprite.cc \ + bitmap.cc \ + cxform.cc \ + font.cc \ + graphic24.cc \ + movie.cc \ + shape.cc \ + sqrt.cc \ + button.cc \ + displaylist.cc \ + graphic.cc \ + graphic32.cc \ + program.cc \ + sound.cc \ + text.cc +OBJECTS = libflashplugin.o \ + libflashpluginimpl.o \ + adpcm.o \ + character.o \ + flash.o \ + graphic16.o \ + matrix.o \ + script.o \ + sprite.o \ + bitmap.o \ + cxform.o \ + font.o \ + graphic24.o \ + movie.o \ + shape.o \ + sqrt.o \ + button.o \ + displaylist.o \ + graphic.o \ + graphic32.o \ + program.o \ + sound.o \ + text.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = +OBJMOC = + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(SYSCONF_LINK_TARGET) + +$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK_LIB) + +moc: $(SRCMOC) + +tmake: Makefile.in + +Makefile.in: libflash.pro + tmake libflash.pro -o Makefile.in + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +libflashplugin.o: libflashplugin.cpp \ + libflashplugin.h \ + flash.h \ + ../mediaplayerplugininterface.h + +libflashpluginimpl.o: libflashpluginimpl.cpp \ + libflashplugin.h \ + flash.h \ + ../mediaplayerplugininterface.h \ + libflashpluginimpl.h \ + ../mediaplayerplugininterface.h + +adpcm.o: adpcm.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +character.o: character.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +flash.o: flash.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h \ + graphic16.h \ + graphic24.h \ + graphic32.h + +graphic16.o: graphic16.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h \ + graphic16.h + +matrix.o: matrix.cc \ + matrix.h + +script.o: script.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +sprite.o: sprite.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +bitmap.o: bitmap.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +cxform.o: cxform.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +font.o: font.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +graphic24.o: graphic24.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h \ + graphic24.h + +movie.o: movie.cc \ + movie.h \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h + +shape.o: shape.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +sqrt.o: sqrt.cc + +button.o: button.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +displaylist.o: displaylist.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +graphic.o: graphic.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +graphic32.o: graphic32.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h \ + graphic32.h + +program.o: program.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +sound.o: sound.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + +text.o: text.cc \ + swf.h \ + flash.h \ + matrix.h \ + cxform.h \ + rect.h \ + jpeglib.h \ + jconfig.h \ + jmorecfg.h \ + jerror.h \ + graphic.h \ + character.h \ + bitmap.h \ + shape.h \ + displaylist.h \ + sound.h \ + button.h \ + font.h \ + text.h \ + adpcm.h \ + program.h \ + sprite.h \ + script.h \ + movie.h + + diff --git a/core/multimedia/opieplayer/libflash/README b/core/multimedia/opieplayer/libflash/README new file mode 100644 index 0000000..9914a00 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/README @@ -0,0 +1,191 @@ + +MODIFICATIONS BY TROLLTECH +-------------------------- + +Oct. 2001 + +Just the Lib directory of the flash library source archive +has been copied in to the QPE CVS tree. For the full source code +to create a KDE screensaver or stand alone player etc, download +the orginal source tar ball from http://www.swift-tools.com/Flash +The files libflashplugin* have been added to wrapper the library +to produce a Qtopia Media Player plugin out of the code. + +John R. + + +INTRODUCTION +------------ + +Jun. 12th 2000 + +This the Version 0.4.10 of the Flash Library for Linux. + +Flash Plugin is under GPL, see COPYING file. + +Provides: +- Lib contains the FlashLib sources. +- Plugin contains plugin sources. +- Player contains the standalone player sources. +- Kflash a Flash KDE screen saver. + +New features: +- Bug fixes. +- 24 and 32 modes supported. +- Flash Library as screen saver (for xcreensaver and KDE). + +To get some information on this library check out the following link : +http://www.swift-tools.com/Flash + +Authors: Olivier Debon + Fabrice Bellard + +FEATURES +-------- + +Limitations : + - The plugin and the player use XShm extensions, so remote display is not possible. + - No Flash 4 features (but no crash on Flash 4 files). + +Not functional : + - No Morphing. + - No vertical anti-aliasing. + +SOUND SUPPORT +------------- + +Limitations : + - No streamed sound supported (interleaved data). + - No sound envelop. So no fading or balancing effect. + +But the main feature is here and sound can be enjoyed. + +I recommend OSS drivers, but it is not required at all +(http://www.opensound.com) + +If you have troubles with sound put the -DNOSOUND option +for compilation. Also do this for non-Linux Unix. + +THE PLAYER +---------- + +The standalone player can simply control movie by +pressing Q to quit, P to pause, C to continue and +R to replay. +There is also the possibility to zoom in or out +and scroll using Keypad +/- and cursor keys, but +it is buggy on frozen images. + +THE SCREEN SAVERS +----------------- + +The standalone player can be run though xscreensaver. Modify +your .xscreensaver file to add swfplayer: +programs: swfplayer -root /home/olivier/Flash/Test/test.swf +(See xscreensaver doc for more details on Xscreensaver). + +For KDE, just install the kflash.kss file from the Kflash +directory in /usr/bin (or where your KDE installation expects +kss file to be). +In your KDE start menu, select Settings->Desktop->Screensaver +Choose 'Flash Movies' and click on SetUp button. You'll have +to select a Flash file (take the test.swf file provided with +this distribution). The fullscreen option will scale the movie +to the entire screen (it can be very CPU intensive). The +enable sound option will allow to play sounds, but as a screen +saver mode this is not a good idea :) + +BUG REPORT +---------- + +If Netscape crashes when it started to play a Flash file, please +report the complete url where you have found the file. +Do not send the actual file ! + +If you have rendering problem also report the url. + +If the plugin does not seem to show anything or does not do what it +is supposed to do, please consider that the plugin does not support +all Flash 2/4 features. Anyway it tries to play it but may fail then. + +COMPILATION +----------- + +If you use Linux just type 'make'. + +Warning : the plugin compilation should not fail, but you may +have problem with Netscape at startup. See INSTALLATION section +for workarounds. + +For other Unices like FreeBSD or Solaris you may have to change +some flags. See Plugin/Makefile for hints. + +INSTALLATION +------------ + +Once you have successfully compiled the plugin, put the file +npflash.so (located in the Plugin directory) into your +~/.netscape/plugins directory or into the system-wide +/opt/netscape/plugins directory (depends on where you have installed +Netscape). + +If Netscape already runs type 'javascript:navigator.plugins.refresh' +in the Location field. + + PROBLEMS + -------- + +If you have problem to successfully install the plugin, please +read the following hints. Otherwise, report the problem with full +description of your configuration : +- Distribution. +- Compiler. +- Libs (the output of ldconfig -p is useful). +- The netscape version and the output of 'ldd netscape'. + +If some symbols like _rtti or _throw are unresolved, it seems +that you have egcs. Just uncomment the proper line in the main +Makefile. +You may then still have some unresolved symbols like __sigsetjmp. +This time, add -DC6R5 in the Plugin/Makefile at the PLUGIN_DEFINES +line. + + CHECKING + -------- + +To verify that the plugin is installed properly, type "about:plugins" +in Netscape's "Location:" or "Netsite:" field. The plugin should show +up there, something like + +___________________________________________________________________________ + + Shockwave Flash + + File name: /opt/netscape/plugins/npflash.so + + Flash file player Version 0.4.10 + + Shockwave is a trademark of Macromedia® + + Author: Olivier Debon + + --------------------------------------------------------------------------------- +| Mime Type | Description | Suffixes | Enabled | +|--------------------------------+-------------------+-------------+--------------| +| application/futuresplash | Flash Plugin | spl | Yes | +| application/x-shockwave-flash | | swf | Yes | + --------------------------------------------------------------------------------- + +___________________________________________________________________________ + + +If it shows up, but the "Enabled" column says "No", you need to +configure the Flash plugin as a helper application. Go to +Edit/Preferences/Navigator/Applications, and add it as follows: + +Description: Flash Plugin +MIME Type: application/x-shockwave-flash +Suffixes: swf +Handled By: Plug In (select "Shockwave Flash") + +------ diff --git a/core/multimedia/opieplayer/libflash/adpcm.cc b/core/multimedia/opieplayer/libflash/adpcm.cc new file mode 100644 index 0000000..a4bc435 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/adpcm.cc @@ -0,0 +1,235 @@ + +#include "swf.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +// This file has been rearranged from the code posted +// on news:forums.macromedia.com by Jonathan Gay. +// Courtesy of Macromedia + +// +// ADPCM tables +// + +static const int indexTable2[2] = { + -1, 2, +}; + +// Is this ok? +static const int indexTable3[4] = { + -1, -1, 2, 4, +}; + +static const int indexTable4[8] = { + -1, -1, -1, -1, 2, 4, 6, 8, +}; + +static const int indexTable5[16] = { + -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16, +}; + +static const int* indexTables[] = { + indexTable2, + indexTable3, + indexTable4, + indexTable5 +}; + +static const int stepsizeTable[89] = { + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 +}; + +long +Adpcm::GetBits(int n) +{ + if ( bitPos < n ) FillBuffer(); + + assert(bitPos >= n); + + long v = ((unsigned long)bitBuf << (32-bitPos)) >> (32-n); + bitPos -= n; + + return v; +} + +long +Adpcm::GetSBits(int n) +{ + if ( bitPos < n ) FillBuffer(); + + assert(bitPos >= n); + + long v = ((long)bitBuf << (32-bitPos)) >> (32-n); + bitPos -= n; + + return v; +} + +// +// The Decompressor +// + +// Constructor +Adpcm::Adpcm(unsigned char *buffer, long isStereo) +{ + stereo = isStereo; + src = buffer; + + nBits = 0; // flag that it is not inited + nSamples = 0; + + bitPos = 0; + bitBuf = 0; +} + +void +Adpcm::FillBuffer() +{ + while ( bitPos <= 24 /*&& srcSize > 0*/ ) { + bitBuf = (bitBuf<<8) | *src++; + bitPos += 8; + } +} + +void +Adpcm::Decompress(short *dst, long n) +{ + if ( nBits == 0 ) { + // Get the compression header + nBits = (int)GetBits(2)+2; + } + + const int* indexTable = indexTables[nBits-2]; + int k0 = 1 << (nBits-2); + int signmask = 1 << (nBits-1); + + if ( !stereo ) { + // Optimize for mono + long vp = valpred[0]; // maybe these can get into registers... + int ind = index[0]; + long ns = nSamples; + + while ( n-- > 0 ) { + ns++; + + if ( (ns & 0xFFF) == 1 ) { + // Get a new block header + *dst++ = (short)(vp = GetSBits(16)); + + ind = (int)GetBits(6); // The first sample in a block does not have a delta + } else { + // Process a delta value + int delta = (int)GetBits(nBits); + + // Compute difference and new predicted value + // Computes 'vpdiff = (delta+0.5)*step/4' + int step = stepsizeTable[ind]; + long vpdiff = 0; + int k = k0; + + do { + if ( delta & k ) + vpdiff += step; + step >>= 1; + k >>= 1; + } while ( k ); + + vpdiff += step; // add 0.5 + + if ( delta & signmask ) // the sign bit + vp -= vpdiff; + else + vp += vpdiff; + + // Find new index value + ind += indexTable[delta&(~signmask)]; + + if ( ind < 0 ) + ind = 0; + else if ( ind > 88 ) + ind = 88; + + // clamp output value + if ( vp != (short)vp ) + vp = vp < 0 ? -32768 : 32767; + + /* Step 7 - Output value */ + *dst++ = (short)vp; + } + } + + valpred[0] = vp; + index[0] = ind; + nSamples = ns; + + } else { + int sn = stereo ? 2 : 1; + + // Stereo + while ( n-- > 0 ) { + + nSamples++; + + if ( (nSamples & 0xFFF) == 1 ) { + // Get a new block header + for ( int i = 0; i < sn; i++ ) { + + *dst++ = (short)(valpred[i] = GetSBits(16)); + + // The first sample in a block does not have a delta + index[i] = (int)GetBits(6); + } + } else { + // Process a delta value + for ( int i = 0; i < sn; i++ ) { + int delta = (int)GetBits(nBits); + + // Compute difference and new predicted value + // Computes 'vpdiff = (delta+0.5)*step/4' + + int step = stepsizeTable[index[i]]; + long vpdiff = 0; + int k = k0; + + do { + if ( delta & k ) vpdiff += step; + step >>= 1; + k >>= 1; + } while ( k ); + vpdiff += step; // add 0.5 + + + if ( delta & signmask ) // the sign bit + valpred[i] -= vpdiff; + else + valpred[i] += vpdiff; + + // Find new index value + index[i] += indexTable[delta&(~signmask)]; + + if ( index[i] < 0 ) + index[i] = 0; + else if ( index[i] > 88 ) + index[i] = 88; + + // clamp output value + if ( valpred[i] != (short)valpred[i] ) + valpred[i] = valpred[i] < 0 ? -32768 : 32767; + + /* Step 7 - Output value */ + *dst++ = (short)valpred[i]; + } + } + } + } +} diff --git a/core/multimedia/opieplayer/libflash/adpcm.h b/core/multimedia/opieplayer/libflash/adpcm.h new file mode 100644 index 0000000..5714c0c --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/adpcm.h @@ -0,0 +1,36 @@ +#ifndef _ADPCM_H_ +#define _ADPCM_H_ + +class Adpcm { + + // Destination format - note we always decompress to 16 bit + long stereo; + int nBits; // number of bits in each sample + + long valpred[2]; // Current state + int index[2]; + + long nSamples; // number of samples decompressed so far + + // Parsing Info + unsigned char *src; + long bitBuf; // this should always contain at least 24 bits of data + int bitPos; + + void FillBuffer(); + + long GetBits(int n); + + long GetSBits(int n); + +public: + Adpcm(unsigned char *buffer, long isStereo); + + void Decompress(short * dst, long n); // return number of good samples +#ifdef DUMP + void dump(BitStream *bs); + void Compress(short *pcm, long n, int bits); +#endif +}; + +#endif /* _ADPCM_H_ */ diff --git a/core/multimedia/opieplayer/libflash/bitmap.cc b/core/multimedia/opieplayer/libflash/bitmap.cc new file mode 100644 index 0000000..03b4588 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/bitmap.cc @@ -0,0 +1,606 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +static unsigned char *inputData; + +// Class variables + +int Bitmap::haveTables = 0; + +struct jpeg_decompress_struct Bitmap::jpegObject; + +struct jpeg_source_mgr Bitmap::jpegSourceManager; + +MyErrorHandler Bitmap::jpegErrorMgr; + +Bitmap::Bitmap(long id, int level) : Character(BitmapType, id ) +{ + pixels = NULL; + alpha_buf = NULL; + colormap = NULL; + nbColors = 0; + defLevel = level; +} + +Bitmap::~Bitmap() +{ + if (pixels) { + delete[] pixels; + } + if (alpha_buf) { + delete[] alpha_buf; + } + if (colormap) + { + delete colormap; + } + if (haveTables) { + jpeg_destroy_decompress(&jpegObject); + haveTables = 0; + } +} + +static void errorExit(j_common_ptr info) +{ + (*info->err->output_message) (info); + longjmp(((MyErrorHandler *)info->err)->setjmp_buffer, 1); +} + +// Methods for Source data manager +static void initSource(struct jpeg_decompress_struct *cInfo) +{ + cInfo->src->bytes_in_buffer = 0; +} + +static boolean fillInputBuffer(struct jpeg_decompress_struct *cInfo) +{ + cInfo->src->next_input_byte = inputData; + cInfo->src->bytes_in_buffer = 1; + inputData++; + + return 1; +} + +static void skipInputData(struct jpeg_decompress_struct *cInfo, long count) +{ + cInfo->src->bytes_in_buffer = 0; + inputData += count; +} + +static boolean resyncToRestart(struct jpeg_decompress_struct *cInfo, int desired) +{ + return jpeg_resync_to_restart(cInfo, desired); +} + +static void termSource(struct jpeg_decompress_struct *cInfo) +{ +} + +long Bitmap::getWidth() +{ + return width; +} + +long Bitmap::getHeight() +{ + return height; +} + +Color * +Bitmap::getColormap(long *n) { + if (n) *n = nbColors; + return colormap; +} + +unsigned char * +Bitmap::getPixels() +{ + return pixels; +} + +// Read Tables and Compressed data to produce an image + +static int +buildJpegAlpha(Bitmap *b, unsigned char *buffer) +{ + z_stream stream; + int status; + unsigned char *data; + + data = new unsigned char[b->width*b->height]; + if (data == NULL) + return -1; + + stream.next_in = buffer; + stream.avail_in = 1; + stream.next_out = data; + stream.avail_out = b->width*b->height; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + + status = inflateInit(&stream); + + while (1) { + status = inflate(&stream, Z_SYNC_FLUSH) ; + if (status == Z_STREAM_END) { + break; + } + if (status != Z_OK) { + printf("Zlib data error : %s\n", stream.msg); + delete data; + return -1; + } + stream.avail_in = 1; + } + + inflateEnd(&stream); + + b->alpha_buf = data; + + return 0; +} + +int +Bitmap::buildFromJpegInterchangeData(unsigned char *stream, int read_alpha, long offset) +{ + struct jpeg_decompress_struct cInfo; + struct jpeg_source_mgr mySrcMgr; + MyErrorHandler errorMgr; + JSAMPROW buffer[1]; + unsigned char *ptrPix; + int stride; + long n; + +#if PRINT&1 + printf("flash: loading jpeg (interchange)\n"); +#endif + + // Kludge to correct some corrupted files + if (stream[1] == 0xd9 && stream[3] == 0xd8) { + stream[3] = 0xd9; + stream[1] = 0xd8; + } + + // Setup error handler + cInfo.err = jpeg_std_error(&errorMgr.pub); + errorMgr.pub.error_exit = errorExit; + + if (setjmp(errorMgr.setjmp_buffer)) { + // JPEG data Error + jpeg_destroy_decompress(&cInfo); + if (pixels) { + delete[] pixels; + pixels = NULL; + } + return -1; + } + + // Set current stream pointer to stream + inputData = stream; + + // Here it's Ok + + jpeg_create_decompress(&cInfo); + + // Setup source manager structure + mySrcMgr.init_source = initSource; + mySrcMgr.fill_input_buffer = fillInputBuffer; + mySrcMgr.skip_input_data = skipInputData; + mySrcMgr.resync_to_restart = resyncToRestart; + mySrcMgr.term_source = termSource; + + // Set default source manager + cInfo.src = &mySrcMgr; + + jpeg_read_header(&cInfo, FALSE); + + jpeg_read_header(&cInfo, TRUE); + cInfo.quantize_colors = TRUE; // Create colormapped image + jpeg_start_decompress(&cInfo); + + // Set objet dimensions + height = cInfo.output_height; + width = cInfo.output_width; + bpl = width; + pixels = new unsigned char [height*width]; + if (pixels == NULL) { + jpeg_finish_decompress(&cInfo); + jpeg_destroy_decompress(&cInfo); + return -1; + } + ptrPix = pixels; + + stride = cInfo.output_width * cInfo.output_components; + + buffer[0] = (JSAMPROW)malloc(stride); + + while (cInfo.output_scanline < cInfo.output_height) { + + jpeg_read_scanlines(&cInfo, buffer, 1); + + memcpy(ptrPix,buffer[0],stride); + + ptrPix+= stride; + } + + free(buffer[0]); + + colormap = new Color[cInfo.actual_number_of_colors]; + if (colormap == NULL) { + delete pixels; + jpeg_finish_decompress(&cInfo); + jpeg_destroy_decompress(&cInfo); + return -1; + } + nbColors = cInfo.actual_number_of_colors; + + for(n=0; n < nbColors; n++) + { + colormap[n].red = cInfo.colormap[0][n]; + colormap[n].green = cInfo.colormap[1][n]; + colormap[n].blue = cInfo.colormap[2][n]; + } + + jpeg_finish_decompress(&cInfo); + jpeg_destroy_decompress(&cInfo); + + if (read_alpha) { + if (buildJpegAlpha(this, stream + offset) < 0) { + return -1; + } + } + return 0; +} + +// Read JPEG image using pre-loaded Tables + +int +Bitmap::buildFromJpegAbbreviatedData(unsigned char *stream) +{ + JSAMPROW buffer[1]; + unsigned char *ptrPix; + int stride; + long n; + int status; + +#if PRINT&1 + printf("flash: loading jpeg (abbreviated)\n"); +#endif + + // Set current stream pointer to stream + inputData = stream; + + // Error handler + if (setjmp(jpegErrorMgr.setjmp_buffer)) { + // JPEG data Error + //jpeg_destroy_decompress(&jpegObject); + if (pixels) { + delete[] pixels; + pixels = NULL; + } + return -1; + } + + // Here it's ok + + jpeg_read_header(&jpegObject, TRUE); + jpegObject.quantize_colors = TRUE; // Create colormapped image + jpeg_start_decompress(&jpegObject); + + // Set objet dimensions + height = jpegObject.output_height; + width = jpegObject.output_width; + bpl = width; + pixels = new unsigned char [height*width]; + if (pixels == NULL) { + jpeg_finish_decompress(&jpegObject); + return -1; + } + ptrPix = pixels; + + stride = jpegObject.output_width * jpegObject.output_components; + + buffer[0] = (JSAMPROW)malloc(stride); + + while (jpegObject.output_scanline < jpegObject.output_height) { + + status = jpeg_read_scanlines(&jpegObject, buffer, 1); + + memcpy(ptrPix,buffer[0],stride); + + ptrPix+= stride; + } + + free(buffer[0]); + + colormap = new Color[jpegObject.actual_number_of_colors]; + if (colormap == NULL) { + jpeg_finish_decompress(&jpegObject); + delete pixels; + return -1; + } + nbColors = jpegObject.actual_number_of_colors; + + for(n=0; n < nbColors; n++) + { + colormap[n].red = jpegObject.colormap[0][n]; + colormap[n].green = jpegObject.colormap[1][n]; + colormap[n].blue = jpegObject.colormap[2][n]; + } + + status = jpeg_finish_decompress(&jpegObject); + + return 0; +} + +// Just init JPEG object and read JPEG Tables + +int +Bitmap::readJpegTables(unsigned char *stream) +{ + if (haveTables) { + //Error, it has already been initialized + return -1; + } + + // Setup error handler + jpegObject.err = jpeg_std_error(&jpegErrorMgr.pub); + jpegErrorMgr.pub.error_exit = errorExit; + + if (setjmp(jpegErrorMgr.setjmp_buffer)) { + // JPEG data Error + jpeg_destroy_decompress(&jpegObject); + return -1; + } + + // Set current stream pointer to stream + inputData = stream; + + // Here it's Ok + + jpeg_create_decompress(&jpegObject); + + // Setup source manager structure + jpegSourceManager.init_source = initSource; + jpegSourceManager.fill_input_buffer = fillInputBuffer; + jpegSourceManager.skip_input_data = skipInputData; + jpegSourceManager.resync_to_restart = resyncToRestart; + jpegSourceManager.term_source = termSource; + + // Set default source manager + jpegObject.src = &jpegSourceManager; + + jpeg_read_header(&jpegObject, FALSE); + + haveTables = 1; + + return 0; +} + +int +Bitmap::buildFromZlibData(unsigned char *buffer, int width, int height, int format, int tableSize, int tableHasAlpha) +{ + z_stream stream; + int status; + unsigned char *data; + int elementSize; + +#if PRINT&1 + printf("flash: loading with zlib\n"); +#endif + + this->width = width; + this->height = height; + this->bpl = width; + + if (tableHasAlpha) { + elementSize = 4; // Cmap is RGBA + } else { + elementSize = 3; // Cmap is RGB + } + + stream.next_in = buffer; + stream.avail_in = 1; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + + tableSize++; + + // Uncompress Color Table + if (format == 3) { + unsigned char *colorTable; + long n; + + // Ajust width for 32 bit padding + width = (width+3)/4*4; + this->width = width; + this->bpl = width; + + depth = 1; + colorTable = new unsigned char[tableSize*elementSize]; + if (colorTable == NULL) { + return -1; + } + + stream.next_out = colorTable; + stream.avail_out = tableSize*elementSize; + + inflateInit(&stream); + + while (1) { + status = inflate(&stream, Z_SYNC_FLUSH); + if (status == Z_STREAM_END) { + break; + } + if (status != Z_OK) { + printf("Zlib cmap error : %s\n", stream.msg); + return -1; + } + stream.avail_in = 1; + // Colormap if full + if (stream.avail_out == 0) { + break; + } + } + + nbColors = tableSize; + + colormap = new Color[nbColors]; + if (colormap == NULL) { + delete colorTable; + return -1; + } + + for(n=0; n < nbColors; n++) { + colormap[n].red = colorTable[n*elementSize+0]; + colormap[n].green = colorTable[n*elementSize+1]; + colormap[n].blue = colorTable[n*elementSize+2]; + if (tableHasAlpha) { + colormap[n].alpha = colorTable[n*elementSize+3]; + } + } + + delete colorTable; + + } else if (format == 4) { + depth = 2; + width = (width+1)/2*2; + this->bpl = width; + } else if (format == 5) { + depth = 4; + } + + data = new unsigned char[depth*width*height]; + if (data == NULL) { + if (colormap) delete colormap; + return -1; + } + + stream.next_out = data; + stream.avail_out = depth*width*height; + + if (format != 3) { + status = inflateInit(&stream); + } + + while (1) { + status = inflate(&stream, Z_SYNC_FLUSH) ; + if (status == Z_STREAM_END) { + break; + } + if (status != Z_OK) { + printf("Zlib data error : %s\n", stream.msg); + delete data; + return -1; + } + stream.avail_in = 1; + } + + inflateEnd(&stream); + + pixels = new unsigned char [height*width]; + if (pixels == NULL) { + if (colormap) delete colormap; + delete data; + return -1; + } + + if (format != 3) { + int n,c; + unsigned char r,g,b,a; + unsigned char *ptr; + + r = g = b = a = 0; /* to supress warnings */ + + nbColors = 0; + colormap = new Color[256]; + if (colormap == NULL) { + delete data; + delete pixels; + return -1; + } + memset(colormap, 0, 256 * sizeof(Color)); + ptr = pixels; + + for(n=0; n < width*height*depth; n+=depth,ptr++) { + + switch (format) { + case 4: + a = 1; + r = (data[n] & 0x78)<<1; + g = ((data[n] & 0x03)<<6) | (data[n+1] & 0xc0)>>2; + b = (data[n+1] & 0x1e)<<3; + break; + case 5: + a = data[n]; + // Reduce color dynamic range + r = data[n+1]&0xe0; + g = data[n+2]&0xe0; + b = data[n+3]&0xe0; + break; + } + for(c=0; c < nbColors; c++) { + if (r == colormap[c].red + && g == colormap[c].green + && b == colormap[c].blue) { + *ptr = c; + break; + } + } + if (c == nbColors) { + if (nbColors == 256) continue; + nbColors++; + if (nbColors == 256) { + //printf("Colormap entries exhausted. After %d scanned pixels\n", n/4); + } + colormap[c].alpha = a; + colormap[c].red = r; + colormap[c].green = g; + colormap[c].blue = b; + *ptr = c; + } + } + } else { + memcpy(pixels, data, width*height); + if (tableHasAlpha) { + int n; + unsigned char *ptr, *alpha; + + alpha_buf = (unsigned char *)malloc(width*height); + ptr = data; + alpha = alpha_buf; + for(n=0; n < width*height; n++, ptr++, alpha++) { + *alpha = colormap[*ptr].alpha; + } + } + } + + delete data; + return 0; +} + diff --git a/core/multimedia/opieplayer/libflash/bitmap.h b/core/multimedia/opieplayer/libflash/bitmap.h new file mode 100644 index 0000000..7925309 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/bitmap.h @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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 _BITMAP_H_ +#define _BITMAP_H_ + +struct MyErrorHandler { + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; +}; + +class Bitmap : public Character { + public: + long width; + long height; + long bpl; + long depth; + + unsigned char *pixels; // Array of Pixels + Color *colormap; // Array of color definitions + long nbColors; + + unsigned char *alpha_buf; // Array of alpha values (no alpha if NULL) + + int defLevel; + +// Class Variables + + static int haveTables; + static struct jpeg_decompress_struct jpegObject; + static struct jpeg_source_mgr jpegSourceManager; + static MyErrorHandler jpegErrorMgr; + +public: + Bitmap(long id, int level = 1); + ~Bitmap(); + + // JPEG handling methods + int buildFromJpegInterchangeData(unsigned char *stream, int alpha, long offset); // Complete + int buildFromJpegAbbreviatedData(unsigned char *stream); // Abbreviated + + // Class Method + static int readJpegTables(unsigned char *stream); // Tables Only + + // ZLIB handling methods + int buildFromZlibData(unsigned char *buffer, + int width, int height, + int format, int tableSize, int tableHasAlpha); + + long getWidth(); + long getHeight(); + Color *getColormap(long *n); + unsigned char *getPixels(); +}; + +#endif /* _BITMAP_H_ */ diff --git a/core/multimedia/opieplayer/libflash/button.cc b/core/multimedia/opieplayer/libflash/button.cc new file mode 100644 index 0000000..7d8369d --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/button.cc @@ -0,0 +1,328 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +#define PRINT 0 + +// Contructor + +Button::Button(long id, int level) : Character(ButtonType, id) +{ + defLevel = level; + actionRecords = 0; + buttonRecords = 0; + conditionList = 0; + reset(); + isMenu = 0; + sound[0] = sound[1] = sound[2] = sound[3] = 0; +} + +// Destructor + +Button::~Button() +{ + if (actionRecords) { + ActionRecord *ar,*del; + for(ar = actionRecords; ar;) { + del = ar; + ar = ar->next; + delete del; + } + } + if (buttonRecords) { + ButtonRecord *br,*del; + for(br = buttonRecords; br;) { + del = br; + br = br->next; + if (del->cxform) + delete del->cxform; + delete del; + } + } + if (conditionList) { + Condition *cond,*del; + for(cond = conditionList; cond;) { + ActionRecord *ar,*d; + + for(ar = cond->actions; ar;) { + d = ar; + ar = ar->next; + delete d; + } + + del = cond; + cond = cond->next; + delete del; + } + } +} + +ButtonRecord * +Button::getButtonRecords() +{ + return buttonRecords; +} + +ActionRecord * +Button::getActionRecords() +{ + return actionRecords; +} + +Sound ** +Button::getSounds() +{ + return sound; +} + +Condition * +Button::getConditionList() +{ + return conditionList; +} + +void +Button::setButtonSound(Sound *s, int state) +{ + if (state >=0 && state < 4) { + sound[state] = s; + } +} + +void +Button::setButtonMenu(int menu) +{ + isMenu = menu; +} + +void +Button::addButtonRecord( ButtonRecord *br ) +{ +#if 0 + /* SURTOUT PAS !!! */ + ButtonRecord **l; + + /* sort by layer */ + l=&buttonRecords; + while (*l != NULL && (*l)->layer < br->layer) l = &(*l)->next; + br->next = *l; + *l = br; +#else + br->next = 0; + + if (buttonRecords == 0) { + buttonRecords = br; + } else { + ButtonRecord *current; + + for(current = buttonRecords; current->next; current = current->next); + + current->next = br; + } +#endif +} + +void +Button::addCondition( long transition ) +{ + Condition *condition; + + condition = new Condition; + if (condition == NULL) return; + + condition->transition = transition; + condition->next = conditionList; + + // Move current actionRecords to this condition + condition->actions = actionRecords; + actionRecords = 0; + + conditionList = condition; +} + +void +Button::addActionRecord( ActionRecord *ar ) +{ + ar->next = 0; + + if (actionRecords == 0) { + actionRecords = ar; + } else { + ActionRecord *current; + + for(current = actionRecords; current->next; current = current->next); + + current->next = ar; + } +} + +void +Button::getRegion(GraphicDevice *gd, Matrix *matrix, void *id, ScanLineFunc scan_line_func) +{ + ButtonRecord *br; + + for (br = buttonRecords; br; br = br->next) + { + if ((br->state & stateHitTest) && br->character /* Temporaire */) { + Matrix mat; + + mat = (*matrix) * br->buttonMatrix; + br->character->getRegion(gd, &mat, id, scan_line_func); + } + } +} + +int +Button::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, ButtonState renderState) +{ + ButtonRecord *br; + int sprite = 0; + Cxform *cxf = 0; + +#if PRINT==2 + printf("Rendering Button %d for State(s) ", getTagId()); +#endif + for (br = buttonRecords; br; br = br->next) + { + if ((br->state & renderState) && br->character != NULL) { + Matrix mat; + +#if PRINT==2 + printf("%d ", br->state); +#endif + mat = (*matrix) * br->buttonMatrix; + + if (cxform) { + cxf = cxform; + } else if (br->cxform) { + cxf = br->cxform; + } + + if (br->character->execute(gd, &mat, cxf)) { + sprite = 1; + } + } + } +#if PRINT==2 + printf("\n"); +#endif + return sprite; +} + +ActionRecord * +Button::getActionFromTransition(ButtonState cur, ButtonState old) +{ + Condition *cond; + long mask; + + if (old == cur) return NULL; + + /* transitions */ + mask = 0; + if (old == stateUp && cur == stateOver) + mask |= 0x001; + else if (old == stateOver && cur == stateUp) + mask |= 0x002; + else if (old == stateOver && cur == stateDown) + mask |= 0x004; + else if (old == stateDown && cur == stateOver) + mask |= 0x008; + + if (!isMenu) { + /* push button transitions (XXX: not quite correct) */ + if (old == stateDown && cur == stateUp) + mask = 0x010; + else if (old == stateUp && cur == stateDown) + mask = 0x020; + /* XXX: what is transition 0x040 ?? */ + } else { + /* menu button transitions (XXX: not quite correct) */ + if (old == stateUp && cur == stateDown) + mask = 0x080; + else if (old == stateDown && cur == stateUp) + mask = 0x100; + } + + for (cond = conditionList; cond; cond = cond->next) { + if (cond->transition & mask) { + return cond->actions; + } + } + return 0; +} + +void +Button::getBoundingBox(Rect *bbox, DisplayListEntry *e) +{ + ButtonRecord *br; + + bbox->reset(); + for (br = buttonRecords; br; br = br->next) + { + if (br->state & e->renderState) { + if (br->character) { + Rect bb; + + bb.reset(); + br->character->getBoundingBox(&bb,e); + transformBoundingBox(bbox, &br->buttonMatrix, &bb, 0); + } + } + } +} + +/* Get current render character, actually it should be a list of characters + so a DisplayList after all */ +Character * +Button::getRenderCharacter(ButtonState state) +{ + ButtonRecord *br; + + for (br = buttonRecords; br; br = br->next) + { + if (br->state & state) { + return br->character; + } + } + return 0; +} + +void +Button::updateButtonState(DisplayListEntry *e) +{ + ButtonRecord *br; + + e->buttonCharacter = 0; + for (br = buttonRecords; br; br = br->next) + { + if (br->state & e->renderState) { + e->buttonCharacter = br->character; + e->buttonMatrix = br->buttonMatrix; + return; + } + } +} diff --git a/core/multimedia/opieplayer/libflash/button.h b/core/multimedia/opieplayer/libflash/button.h new file mode 100644 index 0000000..75781b2 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/button.h @@ -0,0 +1,88 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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 _BUTTON_H_ +#define _BUTTON_H_ + +struct ButtonRecord { + ButtonState state; + Character *character; + long layer; + Matrix buttonMatrix; + Cxform *cxform; + + struct ButtonRecord *next; +}; + +struct Condition { + long transition; + ActionRecord *actions; + + Condition *next; +}; + +class Button : public Character { +public: + long defLevel; + + ButtonRecord *buttonRecords; + ActionRecord *actionRecords; + Condition *conditionList; + + long isMenu; + + Sound *sound[4]; + + Button(long id, int level = 1); + ~Button(); + void addActionRecord( ActionRecord *ar ); + void addButtonRecord( ButtonRecord *br ); + void addCondition( long transition ); + int execute(GraphicDevice *gd, Matrix *matrix, + Cxform *cxform, ButtonState renderState); + ActionRecord *getActionFromTransition(ButtonState currentState, + ButtonState old); + void getRegion(GraphicDevice *gd, Matrix *matrix, + void *id, ScanLineFunc scan_line_func); + ButtonRecord *getButtonRecords(); + void setButtonSound(Sound *, int); + void setButtonMenu(int); + + ActionRecord *getActionRecords(); + Condition *getConditionList(); + Sound **getSounds(); + + void getBoundingBox(Rect *bb, DisplayListEntry *); + + void updateButtonState(DisplayListEntry *); + Character *getRenderCharacter(ButtonState state); + + // Builtin + int isButton() { + return 1; + }; + +#ifdef DUMP + void dump(BitStream *); + void dumpButtonRecords(BitStream *, int putCxform = 0); + void dumpButtonConditions(BitStream *); +#endif +}; + +#endif /* _BUTTON_H_ */ diff --git a/core/multimedia/opieplayer/libflash/character.cc b/core/multimedia/opieplayer/libflash/character.cc new file mode 100644 index 0000000..4b5ce36 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/character.cc @@ -0,0 +1,233 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +///// Character member definitions + +Character::Character(ObjectType objectType, long tagid) +{ + type = objectType; + tagId = tagid; + name = NULL; +} + +Character::~Character() +{ + delete name; +} + +int +Character::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform) +{ + printf("Cannot be executed\n"); + return 0; +} + +ActionRecord * +Character::eventHandler(GraphicDevice *gd, FlashEvent *ev) +{ + fprintf(stderr,"Unable to handle event !!!\n"); + return 0; +} + +int +Character::isButton() +{ + return 0; +} + +int +Character::isSprite(void) +{ + return 0; +} + +char * +Character::getName() +{ + return name; +} + +void +Character::getBoundingBox(Rect *bb, DisplayListEntry *e) +{ + //fprintf(stderr,"Unable to handle getBoundingBox !!!\n"); + bb->xmin = LONG_MAX; + bb->ymin = LONG_MAX; + bb->ymax = LONG_MIN; + bb->ymax = LONG_MIN; + return; +} + +void +Character::getRegion(GraphicDevice *gd, Matrix *matrix, + void *id, ScanLineFunc scan_line_func) +{ + fprintf(stderr,"Unable to handle getRegion !!!\n"); + return; +} + +long +Character::getTagId() +{ + return tagId; +} + +void +Character::reset() +{ +} + +ObjectType +Character::getType() +{ + return type; +} + +char * +Character::getTypeString() +{ + switch (type) { + case BitmapType: + return "Bitmap"; + case FontType: + return "Font"; + case ButtonType: + return "Button"; + case SpriteType: + return "Sprite"; + case ShapeType: + return "Shape"; + case SoundType: + return "Sound"; + case TextType: + return "Text"; + default: + return "Unknown"; + } +} + +void +Character::setName(char* string) +{ + name = strdup(string); +} + +///// Dict methods definitions + +Dict::Dict() +{ + head = 0; +} + +Dict::~Dict() +{ + struct sCharCell *cell,*del; + + for(cell = head; cell;) + { + del = cell; + cell = cell->next; + delete del->elt; + delete del; + } +} + +void +Dict::addCharacter(Character *character) +{ + struct sCharCell *cell; + + cell = new sCharCell; + if (cell == NULL) { + delete character; + return; + } + cell->elt = character; + cell->next = head; + + head = cell; +} + +Character * +Dict::getCharacter(long id) +{ + struct sCharCell *cell; + + for(cell = head; cell; cell = cell->next) + { + if (id == cell->elt->getTagId()) return cell->elt; + } + return 0; +} + +void +Dict::dictRewind() +{ + currentCell = head; +} + +Character * +Dict::dictNextCharacter() +{ + if (currentCell) { + struct sCharCell *cell; + + cell = currentCell; + currentCell = currentCell->next; + return cell->elt; + } else { + return 0; + } +} + +void +Dict::nameCharacter(long id, char *string) +{ + struct sCharCell *cell; + + for(cell = head; cell; cell = cell->next) + { + if (cell->elt->getTagId() == id) { + cell->elt->setName(string); + break; + } + } +} + +#ifdef DUMP +void +Dict::dictSetUnsaved() +{ + struct sCharCell *cell; + + for(cell = head; cell; cell = cell->next) + { + cell->elt->saved = 0; + } +} +#endif diff --git a/core/multimedia/opieplayer/libflash/character.h b/core/multimedia/opieplayer/libflash/character.h new file mode 100644 index 0000000..583cb17 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/character.h @@ -0,0 +1,90 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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 _CHARACTER_H_ +#define _CHARACTER_H_ + +enum ObjectType { + ShapeType, + TextType, + FontType, + SoundType, + BitmapType, + SpriteType, + ButtonType +}; + +class DisplayListEntry; + +// Character definition + +class Character { + long tagId; + ObjectType type; + char *name; + +public: + Character(ObjectType type, long tagId); + virtual ~Character(); + + virtual int execute(GraphicDevice *, Matrix *, Cxform *); // Display, play or whatever + virtual int isButton(void); // True if Character is a button + virtual int isSprite(void); + virtual ActionRecord *eventHandler(GraphicDevice *, FlashEvent *); + virtual void getRegion(GraphicDevice *gd, Matrix *matrix, void *id, ScanLineFunc scan_line_func); + virtual void reset(); // Reset internal state of object + virtual void getBoundingBox(Rect *bb, DisplayListEntry *de); +#ifdef DUMP + virtual void dump(BitStream *main); + + int saved; +#endif + + long getTagId(); // Return tagId + ObjectType getType(); + char *getTypeString(); + char *getName(); + void setName(char *); +}; + +struct sCharCell { + Character *elt; + struct sCharCell *next; +}; + +class Dict { + struct sCharCell *head; + struct sCharCell *currentCell; // Iteration variable for dictNextCharacter + +public: + Dict(); + ~Dict(); + + void addCharacter(Character *character); + void nameCharacter(long id, char *string); + Character *getCharacter(long id); + void dictRewind(); + Character *dictNextCharacter(); + +#ifdef DUMP + void dictSetUnsaved(); +#endif +}; + +#endif /* _CHARACTER_H_ */ diff --git a/core/multimedia/opieplayer/libflash/cxform.cc b/core/multimedia/opieplayer/libflash/cxform.cc new file mode 100644 index 0000000..b448f5d --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/cxform.cc @@ -0,0 +1,79 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#ifdef RCSID +static char *rcsid = "$Id"; +#endif + +long +Cxform::getRed(long v) { + long val; + + val = (long)(ra*v+rb); + if (val > 255) val = 255; + else if (val < 0) val = 0; + return val; +} + +long +Cxform::getGreen(long v) { + long val; + + val = (long)(ga*v+gb); + if (val > 255) val = 255; + else if (val < 0) val = 0; + return val; +} + +long +Cxform::getBlue(long v) { + long val; + + val = (long)(ba*v+bb); + if (val > 255) val = 255; + else if (val < 0) val = 0; + return val; +} + +long +Cxform::getAlpha(long v) { + long val; + + val = (long)(aa*v+ab); + if (val > 255) val = 255; + else if (val < 0) val = 0; + return val; +} + +Color +Cxform::getColor(Color color) { + Color newColor; + + newColor.red = getRed(color.red); + newColor.green = getGreen(color.green); + newColor.blue = getBlue(color.blue); + newColor.alpha = getAlpha(color.alpha); + + return newColor; +} diff --git a/core/multimedia/opieplayer/libflash/cxform.h b/core/multimedia/opieplayer/libflash/cxform.h new file mode 100644 index 0000000..14f7189 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/cxform.h @@ -0,0 +1,46 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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 _CXFORM_H_ +#define _CXFORM_H_ + +struct Color { + unsigned char red,green,blue,alpha; + long pixel; +}; + +struct Cxform +{ + float aa; long ab; // a is multiply factor, b is addition factor + float ra; long rb; + float ga; long gb; + float ba; long bb; + + long getRed(long v); + long getGreen(long v); + long getBlue(long v); + long getAlpha(long v); + Color getColor(Color color); + +#ifdef DUMP + void dump(BitStream *bs, int alpha = 0); +#endif +}; + +#endif /* _CXFORM_H_ */ diff --git a/core/multimedia/opieplayer/libflash/displaylist.cc b/core/multimedia/opieplayer/libflash/displaylist.cc new file mode 100644 index 0000000..d71cfb7 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/displaylist.cc @@ -0,0 +1,708 @@ +//////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +#define PRINT 0 + +void deleteButton(FlashMovie *movie, DisplayListEntry *e) +{ + /* save the focus */ + if (movie->mouse_active == 0 && e->renderState == stateOver) { + movie->lost_over = (Button *)e->character; + movie->cur_focus = NULL; + } + + if (e == movie->cur_focus) { + movie->cur_focus = NULL; + } +} + +void addButton(FlashMovie *movie, DisplayListEntry *e) +{ + if (movie->mouse_active == 0 && + movie->cur_focus == NULL && + movie->lost_over == (Button *)e->character) { + /* restore the lost focus */ + e->renderState = stateOver; + e->oldState = stateOver; + ((Button *)e->character)->updateButtonState(e); + movie->lost_over = NULL; + movie->cur_focus = e; + } +} + +DisplayList::DisplayList(FlashMovie *movie) +{ + list = NULL; + this->movie = movie; + bbox.reset(); + isSprite = 0; +} + +DisplayList::~DisplayList() +{ + clearList(); +} + +void +DisplayList::clearList() +{ + DisplayListEntry *del, *e; + + for(e = list; e;) + { + updateBoundingBox(e); + if (e->character->isButton()) { + deleteButton(movie,e); + } + del = e; + e = e->next; + delete del; + } + list = 0; +} + +DisplayListEntry * +DisplayList::getList() +{ + return list; +} + +static void bbox(Rect *rect, Matrix *m, long x1, long y1) +{ + long x,y; + + x = m->getX(x1,y1); + y = m->getY(x1,y1); + if (x < rect->xmin) rect->xmin = x; + if (x > rect->xmax) rect->xmax = x; + if (y < rect->ymin) rect->ymin = y; + if (y > rect->ymax) rect->ymax = y; +} + +// Update bb to include boundary, optional reset of bb +void transformBoundingBox(Rect *bb, Matrix *matrix, Rect *boundary, int reset) +{ + if (reset) { + bb->reset(); + } + + if (boundary->xmin != LONG_MAX) { + bbox(bb, matrix, boundary->xmin, boundary->ymin); + bbox(bb, matrix, boundary->xmax, boundary->ymin); + bbox(bb, matrix, boundary->xmin, boundary->ymax); + bbox(bb, matrix, boundary->xmax, boundary->ymax); + } +} + +void +DisplayList::placeObject(GraphicDevice *gd,Character *character, long depth, Matrix *matrix, Cxform *cxform, char *name) +{ + DisplayListEntry *n,*e,*prev; + + n = new DisplayListEntry; + if (n == NULL) return; + + n->depth = depth; + n->matrix = matrix; + n->cxform = cxform; + n->character = character; + n->instanceName = name; + n->owner = this; + +#if 0 + printf("Dl %lx: placeObject: depth=%d character=%d cxform=%p\n", + this, n->depth,n->character ? n->character->getTagId() : 0, cxform); +#endif + + if (character == 0 || matrix == 0 || cxform == 0) { + for (e = list; e; prev = e, e = e->next) { + if (e->depth == n->depth) { + if (character == 0) { + n->character = e->character; + } + if (matrix == 0) { + n->matrix = e->matrix; + } + if (cxform == 0) { + n->cxform = e->cxform; + } + break; + } + } + } + + if (n->character == 0) { + // Not found !!! Should not happen + // printf("PlaceObject cannot find character at depth %ld\n", n->depth); + delete n; + return; + } + + prev = 0; + for (e = list; e; prev = e, e = e->next) + { + if (e->depth == n->depth) { + if (e->character->isButton()) { + deleteButton(movie, e); + } + + // Do update, object has moved or been resized + updateBoundingBox(e); + + // Replace object + e->depth = n->depth; + e->matrix = n->matrix; + e->cxform = n->cxform; + e->character = n->character; + /* if it is a button, we must update its state */ + if (e->character->isButton()) { + movie->buttons_updated = 1; + addButton(movie, e); + } + + updateBoundingBox(e); + + delete n; + return; + } + if (e->depth > n->depth) break; + } + /* new object */ + + /* button instantiation */ + if (n->character->isButton()) { + n->renderState = stateUp; + n->oldState = stateUp; + ((Button *)n->character)->updateButtonState(n); + addButton(movie,n); + } + + updateBoundingBox(n); + + if (prev == 0) { + // Object comes at first place + n->next = list; + list = n; + } else { + // Insert object + n->next = prev->next; + prev->next = n; + } +} + + +Character * +DisplayList::removeObject(GraphicDevice *gd,Character *character, long depth) +{ + DisplayListEntry *e,*prev; + + // List should not be empty + if (list == 0) return 0; + +#if 0 + printf("removeObject: depth=%d character=%d\n", + depth,character ? character->getTagId() : 0); +#endif + + prev = 0; + for (e = list; e; prev = e, e = e->next) { + if (e->depth == depth) { + if (prev) { + prev->next = e->next; + } else { + list = e->next; + } + if (character == 0) { + character = e->character; + } + if (e->character->isButton()) { + deleteButton(movie, e); + } + if (e->character->isSprite()) { + ((Sprite*)e->character)->reset(); + } + + updateBoundingBox(e); + + delete e; + return character; + } + } + return 0; // Should not happen +} + +void +DisplayList::updateBoundingBox(DisplayListEntry *e) +{ + Rect rect; + + //rect.reset(); + e->character->getBoundingBox(&rect,e); + transformBoundingBox(&this->bbox, e->matrix, &rect, 0); +} + +int +DisplayList::updateSprites() +{ + Sprite *sprite; + DisplayListEntry *e; + int refresh = 0; + + for (e = this->list; e != NULL; e = e->next) { + if (e->character->isButton() && e->buttonCharacter) { + if (e->buttonCharacter->isSprite()) { + Matrix mat; + + sprite = (Sprite *)e->buttonCharacter; + refresh |= sprite->program->dl->updateSprites(); + refresh |= sprite->program->nestedMovie(this->movie->gd,this->movie->sm, e->matrix, e->cxform); + mat = (*e->matrix) * e->buttonMatrix; + transformBoundingBox(&this->bbox, &mat, + &(sprite->program->dl->bbox), + 0); + } + } + if (e->character->isSprite()) { + sprite = (Sprite *)e->character; + refresh |= sprite->program->dl->updateSprites(); + refresh |= sprite->program->nestedMovie(this->movie->gd,this->movie->sm, e->matrix, e->cxform); + transformBoundingBox(&this->bbox, e->matrix, + &(sprite->program->dl->bbox), + 0); + } + } + return refresh; +} + +/* Function can return either 0,1 or 2 + 0: Nothing match, continue + 1: Something matches, but continue searching + 2: Something matches, but stop searching +*/ + +static int exploreButtons1(Program *prg, void *opaque, + ExploreButtonFunc func) +{ + DisplayListEntry *e; + int ret, ret2 = 0; + + for(e=prg->dl->list; e != NULL; e = e->next) { + if (e->character == NULL) continue; + if (e->character->isButton()) { + ret = func(opaque,prg,e); + if (ret == 2) return ret; // Func asks to return at once !!! + if (ret) ret2 = 1; + } + if (e->character->isSprite()) { + ret = exploreButtons1(((Sprite *)e->character)->program, + opaque,func); + if (ret == 2) return ret; // Func asks to return at once !!! + if (ret) ret2 = 1; + } + } + return ret2; +} + +int exploreButtons(FlashMovie *movie, void *opaque, ExploreButtonFunc func) +{ + CInputScript *script; + int ret; + + script = movie->main; + while (script != NULL) { + if (script->program) { + ret = exploreButtons1(script->program, opaque, func); + if (ret) return ret; + } + script = script->next; + } + return 0; +} + +typedef struct { + long x,y; + int hit; + DisplayListEntry *bhit; +} HitTable; + +static void button_hit_func(void *id, long y, long start, long end) +{ + HitTable *h = (HitTable *) id; + if ( y == h->y && (h->x >= start && h->x < end) ) + h->hit = 1; +} + +typedef struct { + FlashMovie *movie; + DisplayListEntry *bhit; +} ButtonHit; + +static int button_hit(void *opaque, Program *prg, DisplayListEntry *e) +{ + ButtonHit *h = (ButtonHit *) opaque; + HitTable hit_table; + FlashMovie *movie = h->movie; + Rect bb,boundary; + Matrix mat; + ButtonState save; + + hit_table.x = movie->mouse_x; + hit_table.y = movie->mouse_y / FRAC; + hit_table.hit = 0; + + // Compute the bounding box in screen coordinates + save = e->renderState; + e->renderState = stateHitTest; + e->character->getBoundingBox(&boundary,e); + e->renderState = save; + mat = (*movie->gd->adjust) * e->renderMatrix; + transformBoundingBox(&bb, &mat, &boundary, 1); + // Check if mouse is within bb + if (movie->mouse_x < bb.xmin) return 0; + if (movie->mouse_x > bb.xmax) return 0; + if (movie->mouse_y < bb.ymin) return 0; + if (movie->mouse_y > bb.ymax) return 0; + + e->character->getRegion(movie->gd, &e->renderMatrix, + &hit_table, button_hit_func); + + if (hit_table.hit) { + h->bhit = e; + return 1; + } else { + return 0; + } +} + +static int button_reset(void *opaque, Program *prg, DisplayListEntry *e) +{ + if (e->renderState != stateUp) { + e->owner->updateBoundingBox(e); + e->oldState = e->renderState; + e->renderState = stateUp; + ((Button *)e->character)->updateButtonState(e); + e->owner->updateBoundingBox(e); + } + return 0; +} + +/* update the button states according to the current mouse state & return the list of actions */ +void +DisplayList::updateButtons(FlashMovie *movie) +{ + DisplayListEntry *bhit; + ButtonHit h; + + if (movie->mouse_active) { + + h.bhit = NULL; + h.movie = movie; + + exploreButtons(movie, &h, button_hit); + + bhit = h.bhit; + + /* set every button to not hit */ + exploreButtons(movie, NULL, button_reset); + + if (bhit) { + ButtonState state; + + if (movie->button_pressed) { + state = stateDown; + } else { + state = stateOver; + } + if (state != bhit->renderState) { + bhit->owner->updateBoundingBox(bhit); + bhit->renderState = state; + ((Button *)bhit->character)->updateButtonState(bhit); + bhit->owner->updateBoundingBox(bhit); + movie->cur_focus = bhit; + if (movie->cursorOnOff) + movie->cursorOnOff(1,movie->cursorOnOffClientData); + } + } else { + if (movie->cursorOnOff) + movie->cursorOnOff(0,movie->cursorOnOffClientData); + } + } +} + +typedef struct { + ActionRecord *action; // Action to do + Program *prg; // Context program +} ButtonAction; + +static int button_action(void *opaque, Program *prg, DisplayListEntry *e) +{ + ButtonAction *h = (ButtonAction *)opaque; + static ActionRecord actionRefresh; + static ActionRecord soundFx; + Button *b; + ActionRecord **paction; + int n; + + actionRefresh.action = ActionRefresh; + actionRefresh.next = 0; + + soundFx.action = ActionPlaySound; + soundFx.next = &actionRefresh; + + b = (Button *)e->character; + + if (e->oldState != e->renderState) { + + paction = &actionRefresh.next; + + if (b->conditionList) { + *paction = b->getActionFromTransition(e->renderState, e->oldState); + } else if (e->renderState == stateDown) { + /* if the button is pressed and + no condition list is defined*/ + *paction = b->actionRecords; + } + + switch(e->renderState) { + case stateUp: + n = 0; + break; + case stateOver: + n = 1; + break; + default: + /* case stateDown: */ + n = 2; + break; + } + + if (b->sound[n]) { + soundFx.sound = b->sound[n]; + h->action = &soundFx; + } else { + h->action = &actionRefresh; + } + + e->oldState = e->renderState; + + h->prg = prg; + return 2; + } + h->action = 0; // Nothing to do about this + return 0; +} + +int computeActions(FlashMovie *movie, Program **prg, ActionRecord **ar) +{ + ButtonAction h; + + h.action = NULL; + exploreButtons(movie, &h, button_action); + if (h.action) { + *prg = h.prg; + *ar = h.action; + return 1; + } + return 0; +} + +#define FOCUS_ZOOM 1.5 +/* in pixels */ +#define FOCUS_SIZE_MIN 50 +#define FOCUS_TRANSLATE 15 + +int +DisplayList::render(GraphicDevice *gd, Matrix *render_matrix, Cxform *cxform) +{ + DisplayListEntry *e,*cur_focus; + int sprite = 0; + long n = 0; + Cxform cxf,*cxf1; + Rect bb,boundary; + + cur_focus = NULL; + + /* + if (isSprite == 0) { + if (this->bbox.xmin == LONG_MAX) return 0; + gd->updateClippingRegion(&this->bbox, render_matrix); + gd->clearCanvas(); + } + */ + + for (e = list; e; e = e->next) + { +#if PRINT + printf("Character %3d @ %3d\n", e->character ? e->character->getTagId() : 0, e->depth); +#endif + if (e->character) { + Matrix mat; + + if (render_matrix) { + mat = *render_matrix; + } + + if (e->matrix) { + mat = mat * (*e->matrix); + } + + /* fast clipping */ + // If object boundaries are outside current clip region give up with rendering + e->character->getBoundingBox(&boundary,e); + if (boundary.xmin != LONG_MAX) { + Matrix tmat; + + tmat = (*gd->adjust) * mat; + transformBoundingBox(&bb, &tmat, &boundary, 1); + + bb.xmin = bb.xmin >> FRAC_BITS; + bb.ymin = bb.ymin >> FRAC_BITS; + bb.xmax = (bb.xmax + FRAC - 1) >> FRAC_BITS; + bb.ymax = (bb.ymax + FRAC - 1) >> FRAC_BITS; + + if (bb.xmin >= gd->clip_rect.xmax || + bb.xmax <= gd->clip_rect.xmin || + bb.ymin >= gd->clip_rect.ymax || + bb.ymax <= gd->clip_rect.ymin) { + continue; + } + } + + if (cxform == NULL) { + cxf1 = e->cxform; + } + else if (e->cxform == NULL) { + cxf1 = cxform; + } + else { + cxf1 = &cxf; + cxf.ra = cxform->ra * e->cxform->ra; + cxf.ga = cxform->ga * e->cxform->ga; + cxf.ba = cxform->ba * e->cxform->ba; + cxf.aa = cxform->aa * e->cxform->aa; + + cxf.rb = (long)(cxform->ra * e->cxform->rb + cxform->rb); + cxf.gb = (long)(cxform->ga * e->cxform->gb + cxform->gb); + cxf.bb = (long)(cxform->ba * e->cxform->bb + cxform->bb); + cxf.ab = (long)(cxform->aa * e->cxform->ab + cxform->ab); + } + + if (e->character->isButton()) { + Button *b = (Button *) e->character; + + e->renderMatrix = mat; + + if (e->renderState != stateUp && movie->mouse_active == 0) { + cur_focus = e; + ((Button *)e->character)->updateButtonState(e); + } + + if (b->execute(gd, &mat, cxf1, e->renderState)) { + sprite = 1; + } + } else { + if (e->character->execute(gd, &mat, cxf1)) { + sprite = 1; + } + } + + n++; + } + } + +#if 0 + { + /* display the bounding box (debug) */ + Matrix tmat; + long x1,x2,y1,y2; + Color white; + + white.red = 255; + white.green = white.blue = 0; + gd->setForegroundColor(white); + + if (render_matrix) { + tmat = (*gd->adjust) * (*render_matrix); + } else { + tmat = *gd->adjust; + } + x1 = bbox.xmin; + y1 = bbox.ymin; + x2 = bbox.xmax; + y2 = bbox.ymax; + gd->drawLine(tmat.getX(x1,y1),tmat.getY(x1,y1),tmat.getX(x2,y1),tmat.getY(x2,y1),10*FRAC); + gd->drawLine(tmat.getX(x2,y1),tmat.getY(x2,y1),tmat.getX(x2,y2),tmat.getY(x2,y2),10*FRAC); + gd->drawLine(tmat.getX(x2,y2),tmat.getY(x2,y2),tmat.getX(x1,y2),tmat.getY(x1,y2),10*FRAC); + gd->drawLine(tmat.getX(x1,y2),tmat.getY(x1,y2),tmat.getX(x1,y1),tmat.getY(x1,y1),10*FRAC); + bbox.print(); + } +#endif + + // Reset clipping zone + bbox.reset(); + + return sprite; +} + +void +DisplayList::getBoundary(Rect *bb) +{ + DisplayListEntry *e; + Rect boundary; + + bb->reset(); + for (e = list; e; e = e->next) + { + if (e->character) { + e->character->getBoundingBox(&boundary,e); + transformBoundingBox(bb, e->matrix, &boundary, 0); + } + } +} + +extern "C" { + +void dump_buttons(FlashHandle flashHandle) +{ +#if 0 + Rect rect; + DisplayListEntry *e; + FlashMovie *movie; + + movie = (FlashMovie *)flashHandle; + + for (e = movie->first_button; e; e = e->next_button) { + computeBBox(movie,&rect,e); + printf("button: id=%d pos=%d %d %d %d\n", + e->character->getTagId(), + rect.xmin, rect.ymin, rect.xmax, rect.ymax); + } +#endif +} + +} diff --git a/core/multimedia/opieplayer/libflash/displaylist.h b/core/multimedia/opieplayer/libflash/displaylist.h new file mode 100644 index 0000000..536f628 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/displaylist.h @@ -0,0 +1,80 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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 _DISPLAYLIST_H_ +#define _DISPLAYLIST_H_ + +class Character; +class Program; + +struct DisplayList; + +// Display List management +struct DisplayListEntry { + Character *character; + long depth; + Matrix *matrix; + Cxform *cxform; + char *instanceName; + + /* button state */ + ButtonState renderState; + ButtonState oldState; + Character *buttonCharacter; + Matrix buttonMatrix; + Matrix renderMatrix; /* last render matrix */ + + DisplayListEntry *next; + + DisplayList *owner; // Parent +}; + +struct DisplayList { + DisplayListEntry *list; + FlashMovie *movie; + Rect bbox; // Delta clipping region + int isSprite; +public: + DisplayList(FlashMovie *movie); + ~DisplayList(); + DisplayListEntry *getList(); + void clearList(); + void placeObject(GraphicDevice *gd,Character *character, long depth, Matrix *matrix = 0, Cxform *cxform = 0, char *name = 0); + Character *removeObject(GraphicDevice *gd, Character *character, long depth); + + int render(GraphicDevice *gd, Matrix *m = 0, Cxform *cxform = 0); + void updateBoundingBox(DisplayListEntry *); + void updateButtons (FlashMovie *); + void getBoundary(Rect *bb); // Returns boundary of current displayed objects + int updateSprites(); // Update sprites in the display list +}; + +typedef void (*DisplayListFunc)(DisplayListEntry *e, void *opaque); + +void updateButtons(FlashMovie *m); +int computeActions(FlashMovie *m, Program **prog, ActionRecord **ar); +void renderFocus(FlashMovie *movie); + +typedef int (*ExploreButtonFunc)(void *opaque, Program *prg, DisplayListEntry *e); +int exploreButtons(FlashMovie *movie, void *opaque, ExploreButtonFunc func); +void updateBoundingBox(DisplayListEntry *e); +void transformBoundingBox(Rect *bb, Matrix *matrix, Rect *boundary, int reset); +void updateButtonState(DisplayListEntry *e, ButtonState state); + +#endif /* _DISPLAYLIST_H_ */ diff --git a/core/multimedia/opieplayer/libflash/flash.cc b/core/multimedia/opieplayer/libflash/flash.cc new file mode 100644 index 0000000..75d351c --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/flash.cc @@ -0,0 +1,275 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" +#include "graphic16.h" +#include "graphic24.h" +#include "graphic32.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +// Interface with standard C +extern "C" { + +FlashHandle +FlashNew() +{ + FlashMovie *fh; + + fh = new FlashMovie; + + fh->main = new CInputScript; + + return (FlashHandle)fh; +} + +int +FlashParse(FlashHandle flashHandle, int level, char *data, long size) +{ + FlashMovie *fh; + CInputScript *script; + int status = FLASH_PARSE_ERROR; + + fh = (FlashMovie *)flashHandle; + + for(script = fh->main; script != NULL; script = script->next) { + if (script->level == level) { + status = script->ParseData(fh, data, size); + + if (status & FLASH_PARSE_START) { + fh->msPerFrame = 1000/fh->main->frameRate; + script->program->rewindMovie(); + } + break; + } + } + + return status; +} + +void +FlashGetInfo(FlashHandle flashHandle, struct FlashInfo *fi) +{ + FlashMovie *fh; + + fh = (FlashMovie *)flashHandle; + + fi->version = fh->main->m_fileVersion; + fi->frameRate = fh->main->frameRate; + fi->frameCount = fh->main->frameCount; + fi->frameWidth = fh->main->frameRect.xmax - fh->main->frameRect.xmin; + fi->frameHeight = fh->main->frameRect.ymax - fh->main->frameRect.ymin; +} + +long FlashGraphicInit(FlashHandle flashHandle, FlashDisplay *fd) +{ + FlashMovie *fh; + + fh = (FlashMovie *)flashHandle; + + switch (fd->bpp) { + case 4: + fh->gd = new GraphicDevice32(fd); + break; + case 3: + fh->gd = new GraphicDevice24(fd); + break; + case 2: + fh->gd = new GraphicDevice16(fd); + break; + default: + fprintf(stderr, "Unsupported depth\n"); + } + + fh->gd->setMovieDimension(fh->main->frameRect.xmax - fh->main->frameRect.xmin, + fh->main->frameRect.ymax - fh->main->frameRect.ymin); + + return 1; // Ok +} + +void +FlashSoundInit(FlashHandle flashHandle, char *device) +{ + FlashMovie *fh; + + fh = (FlashMovie *)flashHandle; + + fh->sm = new SoundMixer(device); +} + +void +FlashZoom(FlashHandle flashHandle, int zoom) +{ + FlashMovie *fh; + + fh = (FlashMovie *)flashHandle; + + fh->gd->setMovieZoom(zoom); +} + +void +FlashOffset(FlashHandle flashHandle, int x, int y) +{ + FlashMovie *fh; + + fh = (FlashMovie *)flashHandle; + + fh->gd->setMovieOffset(x,y); +} + +long +FlashExec(FlashHandle flashHandle, long flag, + FlashEvent *fe, struct timeval *wakeDate) +{ + FlashMovie *fh; + long wakeUp = 0; + + fh = (FlashMovie *)flashHandle; + + if (fh->main == NULL) return 0; // Not ready + if (fh->main->program == NULL) return 0; // Not ready + if (fh->main->program->nbFrames == 0) return 0; // Still not ready + if (fh->gd == 0) return 0; + + switch (flag & FLASH_CMD_MASK) { + case FLASH_STOP: + fh->main->program->pauseMovie(); + wakeUp = 0; + break; + case FLASH_CONT: + fh->main->program->continueMovie(); + wakeUp = FLASH_STATUS_WAKEUP; + break; + case FLASH_REWIND: + fh->main->program->rewindMovie(); + wakeUp = 0; + break; + case FLASH_STEP: + fh->main->program->nextStepMovie(); + wakeUp = 0; + break; + } + + if (flag & FLASH_WAKEUP) { + // Compute next wakeup time + gettimeofday(wakeDate,0); + wakeDate->tv_usec += fh->msPerFrame*1000; + if (wakeDate->tv_usec > 1000000) { + wakeDate->tv_usec -= 1000000; + wakeDate->tv_sec++; + } + + // Play frame + wakeUp = fh->processMovie(fh->gd, fh->sm); + } + + if (checkFlashTimer(&fh->scheduledTime)) { + if (fh->handleEvent(fh->gd, fh->sm, &fh->scheduledEvent)) { + wakeUp = 1; + } + + setFlashTimer(&fh->scheduledTime, -1); + } + + if (flag & FLASH_EVENT) { + wakeUp = fh->handleEvent(fh->gd, fh->sm, fe); + if (wakeUp) { + /* Wake up at once, except for mouse move (40 ms after) */ + gettimeofday(wakeDate,0); + if (fe->type == FeMouseMove) { + wakeDate->tv_usec += 40*1000; + if (wakeDate->tv_usec > 1000000) { + wakeDate->tv_usec -= 1000000; + wakeDate->tv_sec++; + } + } + } + } + + return wakeUp || (fh->scheduledTime.tv_sec != -1); +} + +void FlashSetGetSwfMethod(FlashHandle flashHandle, void (*getSwf)(char *url, int level, void *clientData), void *clientData) +{ + FlashMovie *fh; + + fh = (FlashMovie *)flashHandle; + + fh->getSwf = getSwf; + fh->getSwfClientData = clientData; +} + + +void +FlashSetCursorOnOffMethod(FlashHandle flashHandle, void (*cursorOnOff)(int , void *), void *clientData) +{ + FlashMovie *fh; + + fh = (FlashMovie *)flashHandle; + + fh->cursorOnOff = cursorOnOff; + fh->cursorOnOffClientData = clientData; +} + +void +FlashSetGetUrlMethod(FlashHandle flashHandle, void (*getUrl)(char *, char *, void *), void *clientData) +{ + FlashMovie *fh; + + fh = (FlashMovie *)flashHandle; + + fh->getUrl = getUrl; + fh->getUrlClientData = clientData; +} + +void +FlashClose(FlashHandle flashHandle) +{ + FlashMovie *fh; + + fh = (FlashMovie *)flashHandle; + + delete fh; +} + +void +FlashSettings(FlashHandle flashHandle, long settings) +{ + FlashMovie *fh; + + fh = (FlashMovie *)flashHandle; + + fh->main->program->modifySettings( settings ); +} + +int shape_size,shape_nb,shaperecord_size,shaperecord_nb,style_size,style_nb; + +void flash_dump(void) +{ + printf("flash: shape_size=%d (nb=%d)\n",shape_size,shape_nb); + printf("flash: shaperecord_size=%d (nb=%d)\n",shaperecord_size,shaperecord_nb); + printf("flash: style_size=%d (nb=%d)\n",style_size,style_nb); +} + +}; /* end of extern C */ diff --git a/core/multimedia/opieplayer/libflash/flash.h b/core/multimedia/opieplayer/libflash/flash.h new file mode 100644 index 0000000..9330713 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/flash.h @@ -0,0 +1,129 @@ +/*/////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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 _FLASH_H_ +#define _FLASH_H_ + +#define PLUGIN_NAME "Shockwave Flash" +#define FLASH_VERSION_STRING "Version 0.4.10" + +/* Flags to pass to FlashExec */ +#define FLASH_WAKEUP 0x01 +#define FLASH_EVENT 0x02 +#define FLASH_CMD 0x04 + +/* Mask to extract commands */ +#define FLASH_CMD_MASK 0xf0 +/* Commands */ +#define FLASH_STOP 0x10 /* Pause the movie */ +#define FLASH_CONT 0x20 /* Continue the movie after pause */ +#define FLASH_REWIND 0x30 /* Rewind the movie and pause */ +#define FLASH_STEP 0x40 /* Frame by frame operation */ + +/* return codes of FlashExec */ +#define FLASH_STATUS_WAKEUP 0x01 /* FlashExec must be called again after a given time */ + +struct FlashInfo { + long frameRate; + long frameCount; + long frameWidth; + long frameHeight; + long version; +}; + +/* Player settings */ +#define PLAYER_LOOP (1<<0) +#define PLAYER_QUALITY (1<<1) +#define PLAYER_MENU (1<<2) + +/* Parser status */ +#define FLASH_PARSE_ERROR 0 +#define FLASH_PARSE_START 1 +#define FLASH_PARSE_NEED_DATA 2 +#define FLASH_PARSE_EOM 4 +#define FLASH_PARSE_WAKEUP 8 +#define FLASH_PARSE_OOM 16 /* Out Of Memory */ + +typedef void *FlashHandle; + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +enum FlashEventType { + FeNone, + FeMouseMove, + FeButtonPress, + FeButtonRelease, + FeRefresh, + FeKeyPress, + /* internal events */ + FeKeyRelease, +}; + +enum FlashKey { + FeKeyUp = 1, + FeKeyDown, + FeKeyLeft, + FeKeyRight, + FeKeyEnter, + FeKeyNext +}; + + + +typedef struct FlashEvent { + enum FlashEventType type; + int x,y; /* Mouse coordinates, + relative to upper-left window corner */ + enum FlashKey key; +} FlashEvent; + +typedef struct FlashDisplay { + void *pixels; + int bpl; /* bytes per line */ + int width; + int height; + int depth; + int bpp; + int flash_refresh; + /* Clipping region */ + int clip_x, clip_y; + int clip_width, clip_height; +} FlashDisplay; + +extern FlashHandle FlashNew(); +extern void FlashGetInfo(FlashHandle fh, struct FlashInfo *fi); +extern long FlashGraphicInit(FlashHandle fh, FlashDisplay *fd); +extern void FlashSoundInit(FlashHandle fh, char *device); +extern int FlashParse(FlashHandle fh, int level, char *data, long size); +extern long FlashExec(FlashHandle fh, long flag, FlashEvent *fe, struct timeval *wakeDate); +extern void FlashClose(FlashHandle fh); +extern void FlashSetGetUrlMethod(FlashHandle flashHandle, void (*getUrl)(char *, char *, void *), void *); +extern void FlashSetGetSwfMethod(FlashHandle flashHandle, void (*getSwf)(char *url, int level, void *clientData), void *clientData); +extern void FlashSetCursorOnOffMethod(FlashHandle flashHandle, void (*cursorOnOff)(int , void *), void *clientData); +extern void FlashZoom(FlashHandle fh, int zoom); +extern void FlashOffset(FlashHandle fh, int x, int y); +extern void FlashSettings(FlashHandle fh, long settings); + +#if defined(__cplusplus) || defined(c_plusplus) +}; +#endif + +#endif /* _FLASH_H_ */ diff --git a/core/multimedia/opieplayer/libflash/font.cc b/core/multimedia/opieplayer/libflash/font.cc new file mode 100644 index 0000000..d937276 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/font.cc @@ -0,0 +1,105 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +SwfFont::SwfFont(long id) : Character(FontType, id) +{ + glyphs = 0; + nbGlyphs = 0; + name = NULL; + setFontName("Unknown"); + flags = (FontFlags)0; + lookUpTable = 0; +} + +SwfFont::~SwfFont() +{ + if (lookUpTable) { + delete lookUpTable; + } + delete name; + delete [] glyphs; +} + +void +SwfFont::setFontFlags(FontFlags f) +{ + flags = f; +} + +char * +SwfFont::getName() +{ + return name; +} + +FontFlags +SwfFont::getFlags() +{ + return flags; +} + +long +SwfFont::getNbGlyphs() +{ + return nbGlyphs; +} + +Shape * +SwfFont::getGlyph(long index) +{ + if (index >= nbGlyphs) return 0; + return &glyphs[index]; +} + +long +SwfFont::getGlyphCode(long index) +{ + if (lookUpTable == 0 || index >= nbGlyphs) return 0; + return lookUpTable[index]; +} + +void +SwfFont::setFontName(char *str) +{ + delete name; + name = new char[strlen(str)+1]; + strcpy(name,str); +} + +void +SwfFont::setFontLookUpTable(long *lut) +{ + lookUpTable = lut; +} + +void +SwfFont::setFontShapeTable(Shape *shapes, long n) +{ + glyphs = shapes; + nbGlyphs = n; +} diff --git a/core/multimedia/opieplayer/libflash/font.h b/core/multimedia/opieplayer/libflash/font.h new file mode 100644 index 0000000..bc151ca --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/font.h @@ -0,0 +1,56 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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 _SWFFONT_H_ +#define _SWFFONT_H_ + +class SwfFont : public Character { + Shape *glyphs; // Array + long nbGlyphs; + char *name; + FontFlags flags; + long *lookUpTable; // Array + + // Font2 + long ascent; + long descent; + long leading; + +public: + SwfFont(long id); + ~SwfFont(); + + void setFontShapeTable(Shape *shapes, long n); + void setFontName(char *str); + void setFontLookUpTable(long *lut); + void setFontFlags(FontFlags f); + long getGlyphCode(long index); + long getNbGlyphs(); + Shape *getGlyph(long index); + + char *getName(); + FontFlags getFlags(); + +#ifdef DUMP + void dump(BitStream *bs); + void dumpFontInfo(BitStream *bs); +#endif +}; + +#endif /* _SWFFONT_H_ */ diff --git a/core/multimedia/opieplayer/libflash/graphic.cc b/core/multimedia/opieplayer/libflash/graphic.cc new file mode 100644 index 0000000..f65011e --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/graphic.cc @@ -0,0 +1,632 @@ +//////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +#define PRINT 0 + +// Public + +GraphicDevice::GraphicDevice(FlashDisplay *fd) +{ + flashDisplay = fd; + + bgInitialized = 0; + + // Reset flash refresh flag + flashDisplay->flash_refresh = 0; + + /* 16 bits, RGB565 */ + redMask = 0xF800; + greenMask = 0x07E0; + blueMask = 0x001F; + + /* should be the actual window size */ + targetWidth = fd->width; + targetHeight = fd->height; + bpl = fd->bpl; + +#if PRINT + printf("Target Width = %d\n", targetWidth); + printf("Target Height = %d\n", targetHeight); +#endif + + zoom = FRAC; + movieWidth = targetWidth; + movieHeight = targetHeight; + + viewPort.xmin = 0; + viewPort.xmax = targetWidth-1; + viewPort.ymin = 0; + viewPort.ymax = targetHeight-1; + + canvasBuffer = (unsigned char *) fd->pixels; + + adjust = new Matrix; + foregroundColor.red = 0; + foregroundColor.green = 0; + foregroundColor.blue = 0; + foregroundColor.alpha = ALPHA_OPAQUE; + + backgroundColor.red = 0; + backgroundColor.green = 0; + backgroundColor.blue = 0; + backgroundColor.alpha = ALPHA_OPAQUE; + + showMore = 0; + + setClipping(0); // Reset + setClipping(1); + + /* polygon rasterizer : handle memory errors ! */ + + height = targetHeight; + segs = (Segment **)malloc(height * sizeof(Segment *)); + memset(segs, 0, height * sizeof(Segment *)); + ymin = height; + ymax = -1; + + seg_pool = (Segment *)malloc(NB_SEGMENT_MAX * sizeof(Segment)); + seg_pool_cur = seg_pool; +} + +GraphicDevice::~GraphicDevice() +{ + free(segs); + free(seg_pool); + + if (adjust) { + delete adjust; + } +} + +Color * +GraphicDevice::getColormap(Color *old, long n, Cxform *cxform) +{ + Color *newCmp; + + newCmp = new Color[n]; + if (newCmp == NULL) return NULL; + + if (cxform) { + for(long i = 0; i < n; i++) + { + newCmp[i] = cxform->getColor(old[i]); + newCmp[i].pixel = allocColor(newCmp[i]); + } + } else { + for(long i = 0; i < n; i++) + { + newCmp[i] = old[i]; + newCmp[i].pixel = allocColor(old[i]); + } + } + + return newCmp; +} + +long +GraphicDevice::getHeight() +{ + return targetHeight; +} + +long +GraphicDevice::getWidth() +{ + return targetWidth; +} + +Color +GraphicDevice::getForegroundColor() +{ + return foregroundColor; +} + +void +GraphicDevice::setForegroundColor(Color color) +{ + foregroundColor = color; +} + +Color +GraphicDevice::getBackgroundColor() +{ + return backgroundColor; +} + +int +GraphicDevice::setBackgroundColor(Color color) +{ + if (bgInitialized == 0) { + backgroundColor = color; + clearCanvas(); + bgInitialized = 1; + return 1; + } + return 0; +} + +void +GraphicDevice::setMovieDimension(long width, long height) +{ + float xAdjust, yAdjust; + + movieWidth = width; + movieHeight = height; + + xAdjust = (float)targetWidth*zoom/(float)width; + yAdjust = (float)targetHeight*zoom/(float)height; + + if (xAdjust < yAdjust) { + adjust->a = xAdjust; + adjust->d = xAdjust; + adjust->ty = ((targetHeight*zoom) - (long)(height * xAdjust))/2; + viewPort.ymin = adjust->ty/zoom; + viewPort.ymax = targetHeight-viewPort.ymin-1; + } else { + adjust->a = yAdjust; + adjust->d = yAdjust; + adjust->tx = ((targetWidth*zoom) - (long)(width * yAdjust))/2; + viewPort.xmin = adjust->tx/zoom; + viewPort.xmax = targetWidth-viewPort.xmin-1; + } + + if (viewPort.xmin < 0) viewPort.xmin = 0; + if (viewPort.ymin < 0) viewPort.ymin = 0; + if (viewPort.xmax >= targetWidth) viewPort.xmax = targetWidth-1; + if (viewPort.ymax >= targetHeight) viewPort.ymax = targetHeight-1; +} + +void +GraphicDevice::setMovieZoom(int z) +{ + z *= FRAC; + if (z <= 0 || z > 100) return; + zoom = z; + setMovieDimension(movieWidth,movieHeight); +} + +void +GraphicDevice::setMovieOffset(long x, long y) +{ + adjust->tx = -zoom*x; + adjust->ty = -zoom*y; +} + +long +GraphicDevice::clip(long &y, long &start, long &end) +{ + long xmin,xend; + + if (y < clip_rect.ymin || + y >= clip_rect.ymax) return 1; + if (end <= start) + return 1; + xmin = clip_rect.xmin * FRAC; + xend = clip_rect.xmax * FRAC; + + if (end <= xmin || start >= xend) return 1; + + if (start < xmin) start = xmin; + if (end > xend) end = xend; + + return 0; +} + +void +GraphicDevice::drawBox(long x1, long y1, long x2, long y2) +{ + int i; + + for(i=0;i= NB_SEGMENT_MAX ) + return NULL; + seg = seg_pool_cur++; + + return seg; +} + +/* add a segment to the current path */ +void +GraphicDevice::addSegment(long x1, long y1, long x2, long y2, + FillStyleDef *f0, + FillStyleDef *f1, + int aa) +{ + Segment *seg,**segs; + long dX, X, Y, ymin, ymax, tmp; + FillStyleDef *ff; + + if ( y1 == y2 ) { + return; + } + + if (y1 < y2) { + ymin = y1; + ymax = y2; + ff = f0; + f0 = f1; + f1 = ff; + } else { + ymin = y2; + ymax = y1; + tmp = x1; + x1 = x2; + x2 = tmp; + } + + if (ymax>>FRAC_BITS < clip_rect.ymin) { + return; + } + if (ymin>>FRAC_BITS > clip_rect.ymax) { + return; + } + + X = x1 << SEGFRAC; + dX = ((x2 - x1)< ymax) { + //printf("Elimine @ y = %d ymin = %d, ymax = %d\n", Y, ymin, seg->ymax); + return; + } + X += dX * (Y-ymin); + + Y >>= FRAC_BITS; + if (Y >= clip_rect.ymax) { + return; + } + + seg = allocSeg(); + if (seg == NULL) { + return; + } + + seg->next = 0; + seg->nextValid = 0; + seg->aa = aa; + seg->ymax = ymax; + seg->x1 = x1; + seg->x2 = x2; + seg->X = X; + seg->dX = dX; + seg->fs[0] = f0; + seg->fs[1] = f1; + + if (Y < this->ymin) this->ymin = Y; + ymax = (seg->ymax + FRAC - 1) >> FRAC_BITS; + if (ymax >= this->height) ymax = this->height-1; + if (ymax > this->ymax) this->ymax = ymax; + + segs = this->segs; + + if (segs[Y] == 0) { + segs[Y] = seg; + } else { + Segment *s,*prev; + + prev = 0; + for(s = segs[Y]; s; prev = s, s = s->next) { + if (s->X > seg->X) { + if (prev) { + prev->next = seg; + seg->next = s; + } else { + seg->next = segs[Y]; + segs[Y] = seg; + } + break; + } + } + if (s == 0) { + prev->next = seg; + seg->next = s; + } + } +} + +inline Segment * +GraphicDevice::progressSegments(Segment * curSegs, long y) +{ + Segment *seg,*prev; + + // Update current segments + seg = curSegs; + prev = 0; + while(seg) + { + if ((y*FRAC) > seg->ymax) { + // Remove this segment, no more valid + if (prev) { + prev->nextValid = seg->nextValid; + } else { + curSegs = seg->nextValid; + } + seg = seg->nextValid; + } else { + seg->X += seg->dX * FRAC; + prev = seg; + seg = seg->nextValid; + } + } + return curSegs; +} + +inline Segment * +GraphicDevice::newSegments(Segment *curSegs, Segment *newSegs) +{ + Segment *s,*seg,*prev; + + s = curSegs; + prev = 0; + + // Check for new segments + for (seg = newSegs; seg; seg=seg->next) + { + // Place it at the correct position according to X + if (curSegs == 0) { + curSegs = seg; + seg->nextValid = 0; + } else { + for(; s; prev = s, s = s->nextValid) + { + if ( s->X > seg->X || + ( (s->X == seg->X) && + ( (seg->x1 == s->x1 && seg->dX < s->dX) || + (seg->x2 == s->x2 && seg->dX > s->dX) + ))) { + // Insert before s + if (prev) { + seg->nextValid = s; + prev->nextValid = seg; + } else { + seg->nextValid = curSegs; + curSegs = seg; + } + break; + } + } + // Append at the end + if (s == 0) { + prev->nextValid = seg; + seg->nextValid = 0; + } + } + + s = seg; + } + + return curSegs; +} + +#if 0 +static void +printSeg(Segment *seg) +{ + /* + printf("Seg %08x : X = %5d, Ft = %d, Cl = %2x/%2x/%2x, Cr = %2x/%2x/%2x, x1=%5d, x2=%5d, ymin=%5d, ymax=%5d\n", seg, + seg->X>>SEGFRAC, + seg->right ? seg->right->type: -1, + seg->left ? seg->left->color.red : -1, + seg->left ? seg->left->color.green : -1, + seg->left ? seg->left->color.blue : -1, + seg->right ? seg->right->color.red : -1, + seg->right ? seg->right->color.green : -1, + seg->right ? seg->right->color.blue : -1, + seg->x1, seg->x2, seg->ymin, seg->ymax); + */ +} +#endif + +inline void +GraphicDevice::renderScanLine(long y, Segment *curSegs) +{ + Segment *seg; + long width; + int fi = 1; + FillStyleDef *f; + + width = targetWidth * FRAC; + + if (curSegs && curSegs->fs[0] && curSegs->fs[1] == 0) { + fi = 0; + } + for(seg = curSegs; seg && seg->nextValid; seg = seg->nextValid) + { + if (seg->nextValid->X <0) continue; + if ((seg->X>>SEGFRAC) > width) break; + f = seg->fs[fi]; + if (f) { + switch (f->type) { + case f_Solid: + if (seg->aa) { + fillLineAA(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC); + } else { + fillLine(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC); + } + break; + case f_TiledBitmap: + case f_clippedBitmap: + fillLineBitmap(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC); + break; + case f_LinearGradient: + fillLineLG(&f->gradient, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC); + break; + case f_RadialGradient: + fillLineRG(&f->gradient, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC); + break; + case f_None: + break; + } + } + } +} + +/* draw the current path */ +void +GraphicDevice::drawPolygon(void) +{ + long y; + Segment *curSegs,*seg; + + // no segments ? + if (this->ymax == -1) + return; + + // Foreach scanline + curSegs = 0; + for(y=this->ymin; y <= this->ymax; y++) { + + // Make X values progess and remove unuseful segments + curSegs = progressSegments(curSegs, y); + + // Add the new segment starting at the y position. + curSegs = newSegments(curSegs, this->segs[y]); + + // Render the scanline + if (this->scan_line_func == NULL) { + renderScanLine(y, curSegs); + } else { + for(seg = curSegs; seg && seg->nextValid; seg = seg->nextValid) { + if (seg->nextValid->X >= seg->X) { + scan_line_func(this->scan_line_func_id, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC); + } + } + } + } + + /* free the segments */ + memset(this->segs + this->ymin, 0, + (this->ymax - this->ymin + 1) * sizeof(Segment *)); + + this->ymax = -1; + this->ymin = this->height; + + this->seg_pool_cur = this->seg_pool; +} + +void +GraphicDevice::updateClippingRegion(Rect *rect) +{ + if (!clipping) return; + + transformBoundingBox(&clip_rect, adjust, rect, 1); + clip_rect.xmin >>= FRAC_BITS; + clip_rect.xmax >>= FRAC_BITS; + clip_rect.ymin >>= FRAC_BITS; + clip_rect.ymax >>= FRAC_BITS; + + clip_rect.xmin-=2; + clip_rect.ymin-=2; + clip_rect.xmax+=2; + clip_rect.ymax+=2; + + if (clip_rect.xmin < viewPort.xmin) clip_rect.xmin = viewPort.xmin; + if (clip_rect.xmax < viewPort.xmin) clip_rect.xmax = viewPort.xmin; + if (clip_rect.ymin < viewPort.ymin) clip_rect.ymin = viewPort.ymin; + if (clip_rect.ymax < viewPort.ymin) clip_rect.ymax = viewPort.ymin; + + if (clip_rect.xmax > viewPort.xmax) clip_rect.xmax = viewPort.xmax; + if (clip_rect.ymax > viewPort.ymax) clip_rect.ymax = viewPort.ymax; + if (clip_rect.xmin > viewPort.xmax) clip_rect.xmin = viewPort.xmax; + if (clip_rect.ymin > viewPort.ymax) clip_rect.ymin = viewPort.ymax; +} + +void +GraphicDevice::setClipping(int value) +{ + clipping = value; + if (clipping == 0) { + // Reset region + clip_rect.xmin = viewPort.xmin; + clip_rect.xmax = viewPort.xmax; + clip_rect.ymin = viewPort.ymin; + clip_rect.ymax = viewPort.ymax; + } +} + +// Virtual +void +GraphicDevice::clearCanvas() +{ +} + +long +GraphicDevice::allocColor(Color color) +{ + return 0; +} + +void +GraphicDevice::fillLineBitmap(FillStyleDef *f, long y, long start, long end) +{ +} + +void +GraphicDevice::fillLineLG(Gradient *grad, long y, long start, long end) +{ +} + +void +GraphicDevice::fillLineRG(Gradient *grad, long y, long start, long end) +{ +} + +void +GraphicDevice::fillLine(FillStyleDef *f, long y, long start, long end) +{ +} + +void +GraphicDevice::fillLineAA(FillStyleDef *f, long y, long start, long end) +{ +} + +void +GraphicDevice::drawLine(long x1, long y1, long x2, long y2, long width) +{ +} diff --git a/core/multimedia/opieplayer/libflash/graphic.h b/core/multimedia/opieplayer/libflash/graphic.h new file mode 100644 index 0000000..63ebd99 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/graphic.h @@ -0,0 +1,174 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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 _GRAPHIC_H_ +#define _GRAPHIC_H_ + +#define ALPHA_OPAQUE 255 + +enum FillType { + f_Solid = 0x00, + f_LinearGradient = 0x10, + f_RadialGradient = 0x12, + f_TiledBitmap = 0x40, + f_clippedBitmap = 0x41, + f_None = 0x80 +}; + +struct Gradient { + int nbGradients; + unsigned char ratio[8]; + Color color[8]; + // For rendering + Color *ramp; + Matrix imat; + int has_alpha; +}; + + +struct FillStyleDef { + FillType type; // See enum FillType + + // Solid + Color color; + + // Gradient + Gradient gradient; + + // Bitmap + Bitmap *bitmap; + Matrix bitmap_matrix; + Color *cmap; + unsigned char *alpha_table; + + // Gradient or Bitmap + Matrix matrix; + + FillStyleDef() { + style_size += sizeof(FillStyleDef); + style_nb++; + } +}; + +struct Segment { + long x1,x2; + long ymax; + FillStyleDef *fs[2]; // 0 is left 1 is right + int aa; + long dX; + long X; + + struct Segment *next; + struct Segment *nextValid; +}; + +/* fractional bits (we don't use twips here... too expensive) */ +#define FRAC_BITS 5 +#define FRAC (1 << FRAC_BITS) +#define NB_SEGMENT_MAX (2048*4) +#define SEGFRAC 8 + +class GraphicDevice { + int targetWidth; + int targetHeight; + Rect viewPort; + int movieWidth; + int movieHeight; + int zoom; + unsigned long redMask; + unsigned long greenMask; + unsigned long blueMask; + int clipping; + +public: + FlashDisplay *flashDisplay; + int bgInitialized; + Color backgroundColor; + Color foregroundColor; + +public: + void *scan_line_func_id; + ScanLineFunc scan_line_func; + Rect clip_rect; + +private: + Segment **segs; + int ymin,ymax; + int height; + Segment *seg_pool; + Segment *seg_pool_cur; + + Segment * allocSeg(); + Segment * progressSegments(Segment * curSegs, long y); + Segment * newSegments(Segment *curSegs, Segment *newSegs); + void renderScanLine(long y, Segment *curSegs); + +protected: + long clip(long &y, long &start, long &end); + +public: + Matrix *adjust; // Matrix to fit window (shrink or expand) + + long showMore; // Used for debugging + + // For Direct Graphics + unsigned char *canvasBuffer; // A pointer to canvas'memory + long bpl; // Bytes per line + long bpp; // Bytes per pixel + long pad; // Scanline pad in byte + + GraphicDevice(FlashDisplay *fd); + virtual ~GraphicDevice(); + + int setBackgroundColor(Color); + void setForegroundColor(Color); + Color getBackgroundColor(); + Color getForegroundColor(); + void setMovieDimension(long width, long height); + void setMovieZoom(int zoom); + void setMovieOffset(long x, long y); + long getWidth(); + long getHeight(); + Color *getColormap(Color *old, long n, Cxform *cxform); + + void drawBox(long x1, long y1, long x2, long y2); + + void addSegment(long x1, long y1, long x2, long y2, + FillStyleDef *f0, + FillStyleDef *f1, + int aa); + + void drawPolygon(void); + + void updateClippingRegion(Rect *); + void setClipping(int); + + // Virtual functions + virtual void clearCanvas(); + virtual long allocColor(Color color); + virtual void fillLineBitmap(FillStyleDef *f, long y, long start, long end); + virtual void fillLineLG(Gradient *grad, long y, long start, long end); + virtual void fillLineRG(Gradient *grad, long y, long start, long end); + virtual void fillLine(FillStyleDef *f, long y, long start, long end); + virtual void fillLineAA(FillStyleDef *f, long y, long start, long end); + virtual void drawLine(long x1, long y1, long x2, long y2, long width); + +}; + +#endif /* _GRAPHIC_H_ */ diff --git a/core/multimedia/opieplayer/libflash/graphic16.cc b/core/multimedia/opieplayer/libflash/graphic16.cc new file mode 100644 index 0000000..24d0c20 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/graphic16.cc @@ -0,0 +1,658 @@ +//////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#include "graphic16.h" + +extern unsigned char SQRT[]; + +#define FULL_AA + +#define PRINT 0 + +typedef unsigned short TYPE; + +GraphicDevice16::GraphicDevice16(FlashDisplay *fd) : GraphicDevice(fd) +{ +} + +long +GraphicDevice16::allocColor(Color color) +{ + return (color.red >> 3)<<11 | (color.green>>2)<<5 | (color.blue>>3); +} + +void +GraphicDevice16::clearCanvas() +{ + TYPE pixel; + TYPE *point,*p; + long h, w,n; + + if (!bgInitialized) return; + + pixel = allocColor(backgroundColor); + + point = (TYPE *)(canvasBuffer + clip_rect.ymin * bpl) + clip_rect.xmin; + w = clip_rect.xmax - clip_rect.xmin; + h = clip_rect.ymax - clip_rect.ymin; + + while (h--) { + p = point; + n = w; + while (n--) { + *p++ = pixel; + } + + point = (TYPE *)((char *)point + bpl); + } + + flashDisplay->flash_refresh = 1; + flashDisplay->clip_x = clip_rect.xmin; + flashDisplay->clip_y = clip_rect.ymin; + flashDisplay->clip_width = clip_rect.xmax-clip_rect.xmin; + flashDisplay->clip_height = clip_rect.ymax-clip_rect.ymin; +} + +#define RED_MASK 0xF800 +#define GREEN_MASK 0x07E0 +#define BLUE_MASK 0x001F + +/* alpha = 0 : select c1, alpha = 255 select c2 */ +static inline unsigned long +mix_alpha(unsigned long c1, + unsigned long c2, int alpha) +{ + long r1,r2,r; + long g1,g2,g; + long b1,b2,b; + + r1 = c1 & RED_MASK; + r2 = c2 & RED_MASK; + r = (((r2-r1)*alpha + r1 * 256) >> 8) & RED_MASK; + + g1 = c1 & GREEN_MASK; + g2 = c2 & GREEN_MASK; + g = (((g2-g1)*alpha + g1 * 256) >> 8) & GREEN_MASK; + + b1 = c1 & BLUE_MASK; + b2 = c2 & BLUE_MASK; + b = (((b2-b1)*alpha + b1 * 256) >> 8) & BLUE_MASK; + + return (r|g|b); +} + +void +GraphicDevice16::fillLineAA(FillStyleDef *f, long y, long start, long end) +{ + register long n; + TYPE *line; + TYPE *point,pixel; + unsigned int alpha, start_alpha,end_alpha; + + if (clip(y,start,end)) return; + + line = (TYPE *)(canvasBuffer + bpl*y); + + alpha = f->color.alpha; + pixel = f->color.pixel; + + if (alpha == ALPHA_OPAQUE) { + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start >>= FRAC_BITS; + end >>= FRAC_BITS; + + point = &line[start]; + + if (start == end) { + *point = mix_alpha(*point, pixel, start_alpha + end_alpha - 255); + } else { + n = end-start; + if (start_alpha < 255) { + *point = mix_alpha(*point, pixel, start_alpha); + point++; + n--; + } + while (n > 0) { + *point = pixel; + point++; + n--; + } + if (end_alpha > 0) { + *point = mix_alpha(*point, pixel, end_alpha); + } + } + } else { + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start >>= FRAC_BITS; + end >>= FRAC_BITS; + + point = &line[start]; + + if (start == end) { + *point = mix_alpha(*point, pixel, + ((start_alpha + end_alpha - 255) * alpha) >> 8); + } else { + n = end-start; + if (start_alpha < 255) { + *point = mix_alpha(*point, pixel, (start_alpha * alpha) >> 8); + point++; + n--; + } + while (n > 0) { + *point = mix_alpha(*point, pixel, alpha); + point++; + n--; + } + if (end_alpha > 0) { + *point = mix_alpha(*point, pixel, (end_alpha * alpha) >> 8); + } + } + } +} + +void +GraphicDevice16::fillLine(FillStyleDef *f, long y, long start, long end) +{ + register long n; + TYPE *line,*point; + TYPE pixel; + unsigned int alpha; + + if (clip(y,start,end)) return; + + start >>= FRAC_BITS; + end >>= FRAC_BITS; + + line = (TYPE *)(canvasBuffer + bpl*y); + point = &line[start]; + n = end-start; + pixel = f->color.pixel; + alpha = f->color.alpha; + if (alpha == ALPHA_OPAQUE) { + while (n--) { + *point = pixel; + point++; + } + } else { + while (n--) { + *point = mix_alpha(*point, pixel, alpha); + point++; + } + } +} + +void +GraphicDevice16::fillLineBitmap(FillStyleDef *f, long y, long start, long end) +{ + int n; + long x1,y1,dx,dy; + Matrix *m = &f->bitmap_matrix; + Bitmap *b = f->bitmap; + unsigned char *pixels; + TYPE *p; + Color *cmap; + long pixbpl; + TYPE pixel; + int offset; + unsigned char *alpha_table; + + /* safety test) */ + if (!b) return; + + if (clip(y,start,end)) return; + + start /= FRAC; + end /= FRAC; + n = end - start; + p = (TYPE *) (this->canvasBuffer + this->bpl*y + start * 2); + + /* the coordinates in the image are normalized to 16 bits */ + x1 = (long) (m->a * start + m->b * y + m->tx); + y1 = (long) (m->c * start + m->d * y + m->ty); + dx = (long) (m->a); + dy = (long) (m->c); + + pixels = b->pixels; + pixbpl = b->bpl; + cmap = f->cmap; + + if (b->alpha_buf == NULL) { + while (n) { + if (x1 >= 0 && y1 >= 0 && + (x1 >> 16) < b->width && (y1 >> 16) < b->height) { + + pixel = cmap[pixels[(y1 >> 16) * pixbpl + (x1 >> 16)]].pixel; + *p = pixel; + } + x1 += dx; + y1 += dy; + p++; + n--; + } + } else if (f->alpha_table) { + alpha_table = f->alpha_table; + while (n) { + if (x1 >= 0 && y1 >= 0 && + (x1 >> 16) < b->width && (y1 >> 16) < b->height) { + + offset = (y1 >> 16) * pixbpl + (x1 >> 16); + pixel = cmap[pixels[offset]].pixel; + *p = mix_alpha(*p, pixel, alpha_table[b->alpha_buf[offset]]); + } + x1 += dx; + y1 += dy; + p++; + n--; + } + } else { + while (n) { + if (x1 >= 0 && y1 >= 0 && + (x1 >> 16) < b->width && (y1 >> 16) < b->height) { + + offset = (y1 >> 16) * pixbpl + (x1 >> 16); + pixel = cmap[pixels[offset]].pixel; + *p = mix_alpha(*p, pixel, b->alpha_buf[offset]); + } + x1 += dx; + y1 += dy; + p++; + n--; + } + } +} + +void +GraphicDevice16::fillLineLG(Gradient *grad, long y, long start, long end) +{ + long dr,r,v,r2; + register long n; + TYPE *line; + TYPE *point; + Color *cp,*ramp; + Matrix *m = &grad->imat; + unsigned int start_alpha,end_alpha; + + if (clip(y,start,end)) return; + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start /= FRAC; + end /= FRAC; + + n = end-start; + + r = (long) (m->a * start + m->b * y + m->tx); + dr = (long) (m->a); + + ramp = grad->ramp; + + line = (TYPE *)(canvasBuffer + bpl*y); + point = &line[start]; + + r2 = r + n * dr; + if ( ((r | r2) & ~255) == 0 ) { + if (!grad->has_alpha) { +#ifdef FULL_AA + if (start_alpha < 255) { + v = r>>16; + *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha); + point++; + r += dr; + n--; + } +#endif /* FULL_AA */ + while (n>0) { + v = r>>16; + *point = (TYPE)ramp[v].pixel; + point++; + r += dr; + n--; + } +#ifdef FULL_AA + if (end_alpha > 0) { + v = r>>16; + *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha); + } +#endif /* FULL_AA */ + } else { + while (n--) { + v = r>>16; + cp = &ramp[v]; + *point = mix_alpha(*point, cp->pixel, cp->alpha); + point++; + r += dr; + } + } + } else { + if (!grad->has_alpha) { +#ifdef FULL_AA + if (start_alpha < 255) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha); + point++; + r += dr; + n--; + } +#endif /* FULL_AA */ + while (n>0) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + *point = (TYPE)ramp[v].pixel; + point++; + r += dr; + n--; + } +#ifdef FULL_AA + if (end_alpha > 0) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha); + } +#endif /* FULL_AA */ + } else { + while (n--) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + cp = &ramp[v]; + *point = mix_alpha(*point, cp->pixel, cp->alpha); + point++; + r += dr; + } + } + } +} + +void +GraphicDevice16::fillLineRG(Gradient *grad, long y, long start, long end) +{ + long X,dx,r,Y,dy; + long dist2; + register long n; + Color *cp,*ramp; + TYPE *line; + TYPE *point; + Matrix *m = &grad->imat; + unsigned int start_alpha,end_alpha; + + if (clip(y,start,end)) return; + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start /= FRAC; + end /= FRAC; + + n = end-start; + + X = (long) (m->a * start + m->b * y + m->tx); + Y = (long) (m->c * start + m->d * y + m->ty); + dx = (long) (m->a); + dy = (long) (m->c); + + ramp = grad->ramp; + + line = (TYPE *)(canvasBuffer + bpl*y); + point = &line[start]; + + if (!grad->has_alpha) { +#ifdef FULL_AA + if (start == end) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r = SQRT[dist2]; + } + *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha + end_alpha - 255); + } else { + if (start_alpha < 255) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r = SQRT[dist2]; + } + *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha); + point++; + X += dx; + Y += dy; + n--; + } +#endif /* FULL_AA */ + while (n>0) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r= SQRT[dist2]; + } + *point = (TYPE)ramp[r].pixel; + point++; + X += dx; + Y += dy; + n--; + } +#ifdef FULL_AA + if (end_alpha > 0) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r= SQRT[dist2]; + } + *point = mix_alpha(*point, (TYPE)ramp[r].pixel, end_alpha); + } + } +#endif /* FULL_AA */ + + } else { + while (n--) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r= SQRT[dist2]; + } + cp = &ramp[r]; + *point = mix_alpha(*point, cp->pixel, cp->alpha); + point++; + X += dx; + Y += dy; + } + } +} + +void +GraphicDevice16::drawLine(long x1, long y1, long x2, long y2, long width) +{ + int n,adr,dx,dy,sx,color; + register int a; + register TYPE *pp; + int alpha; + + x1 = (x1) >> FRAC_BITS; + y1 = (y1) >> FRAC_BITS; + x2 = (x2) >> FRAC_BITS; + y2 = (y2) >> FRAC_BITS; + + if (y1 > y2 || (y1 == y2 && x1 > x2)) { + long tmp; + + tmp=x1; + x1=x2; + x2=tmp; + + tmp=y1; + y1=y2; + y2=tmp; + } + + if (y1 == y2 && (y1 < clip_rect.ymin || y1 > clip_rect.ymax)) return; + if (x1 == x2 && (x1 < clip_rect.xmin || x1 > clip_rect.xmax)) return; + if (x1 == x2 && y1 == y2) return; // Bad !!! + + if (y1 < clip_rect.ymin && y1 != y2) { + x1 += (x2-x1)*(clip_rect.ymin-y1)/(y2-y1); + y1 = clip_rect.ymin; + } + + if (y2 > clip_rect.ymax && y1 != y2) { + x2 -= (x2-x1)*(y2-clip_rect.ymax)/(y2-y1); + y2 = clip_rect.ymax; + } + + if (x1 < x2) { + if (x1 < clip_rect.xmin && x1 != x2) { + y1 += (y2-y1)*(clip_rect.xmin-x1)/(x2-x1); + x1 = clip_rect.xmin; + } + + if (x2 > clip_rect.xmax && x1 != x2) { + y2 -= (y2-y1)*(x2-clip_rect.xmax)/(x2-x1); + x2 = clip_rect.xmax; + } + } + + if (x1 > x2) { + if (x2 < clip_rect.xmin && x2 != x1) { + y2 -= (y2-y1)*(clip_rect.xmin-x2)/(x1-x2); + x2 = clip_rect.xmin; + } + + if (x1 > clip_rect.xmax && x2 != x1) { + y1 += (y2-y1)*(x1-clip_rect.xmax)/(x1-x2); + x1 = clip_rect.xmax; + } + } + + // Check again + if (x1 == x2 && y1 == y2) return; + if (x1 < clip_rect.xmin || x2 < clip_rect.xmin) return; + if (y1 < clip_rect.ymin || y2 < clip_rect.ymin) return; + if (x1 > clip_rect.xmax || x2 > clip_rect.xmax) return; + if (y1 > clip_rect.ymax || y2 > clip_rect.ymax) return; + + sx=bpl >> 1; + adr=(y1 * sx + x1); + pp = (TYPE *)canvasBuffer + adr; + + dx = x2 - x1; + dy = y2 - y1; + + color = allocColor(foregroundColor); + alpha = foregroundColor.alpha; + + if (alpha == ALPHA_OPAQUE) { + +#define PUTPIXEL() \ + { \ + *pp=color; \ + } + +#define DRAWLINE(dx,dy,inc_1,inc_2) \ + n=dx;\ + a=2*dy-dx;\ + dy=2*dy;\ + dx=2*dx-dy;\ + do {\ + PUTPIXEL();\ + if (a>0) { pp+=(inc_1); a-=dx; }\ + else { pp+=(inc_2); a+=dy; }\ + } while (--n >= 0); + +/* fin macro */ + + if (dx == 0 && dy == 0) { + PUTPIXEL(); + } else if (dx > 0) { + if (dx >= dy) { + DRAWLINE(dx, dy, sx + 1, 1); + } else { + DRAWLINE(dy, dx, sx + 1, sx); + } + } else { + dx = -dx; + if (dx >= dy) { + DRAWLINE(dx, dy, sx - 1, -1); + } else { + DRAWLINE(dy, dx, sx - 1, sx); + } + } + + +#undef DRAWLINE +#undef PUTPIXEL + } else { +#define PUTPIXEL() \ + { \ + *pp=mix_alpha(*pp,color,alpha); \ + } + +#define DRAWLINE(dx,dy,inc_1,inc_2) \ + n=dx;\ + a=2*dy-dx;\ + dy=2*dy;\ + dx=2*dx-dy;\ + do {\ + PUTPIXEL();\ + if (a>0) { pp+=(inc_1); a-=dx; }\ + else { pp+=(inc_2); a+=dy; }\ + } while (--n >= 0); + +/* fin macro */ + + if (dx == 0 && dy == 0) { + PUTPIXEL(); + } else if (dx > 0) { + if (dx >= dy) { + DRAWLINE(dx, dy, sx + 1, 1); + } else { + DRAWLINE(dy, dx, sx + 1, sx); + } + } else { + dx = -dx; + if (dx >= dy) { + DRAWLINE(dx, dy, sx - 1, -1); + } else { + DRAWLINE(dy, dx, sx - 1, sx); + } + } + + +#undef DRAWLINE +#undef PUTPIXEL + } +} diff --git a/core/multimedia/opieplayer/libflash/graphic16.h b/core/multimedia/opieplayer/libflash/graphic16.h new file mode 100644 index 0000000..938d856 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/graphic16.h @@ -0,0 +1,39 @@ +//////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +class GraphicDevice16: public GraphicDevice { +private: + long GraphicDevice16::allocColor(Color color); + +public: + GraphicDevice16(FlashDisplay *fd); + + void clearCanvas(); + void fillLineAA(FillStyleDef *f, long y, long start, long end); + void fillLine(FillStyleDef *f, long y, long start, long end); + void fillLineBitmap(FillStyleDef *f, long y, long start, long end); + void fillLineLG(Gradient *grad, long y, long start, long end); + void fillLineRG(Gradient *grad, long y, long start, long end); + void drawLine(long x1, long y1, long x2, long y2, long width); +}; diff --git a/core/multimedia/opieplayer/libflash/graphic24.cc b/core/multimedia/opieplayer/libflash/graphic24.cc new file mode 100644 index 0000000..6d15019 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/graphic24.cc @@ -0,0 +1,648 @@ +//////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#include "graphic24.h" + +extern unsigned char SQRT[]; + +#define FULL_AA + +#define PRINT 0 + +typedef unsigned char TYPE; +#define BPP 3 + +GraphicDevice24::GraphicDevice24(FlashDisplay *fd) : GraphicDevice(fd) +{ +} + +long +GraphicDevice24::allocColor(Color color) +{ + return 0; +} + +void +GraphicDevice24::clearCanvas() +{ + TYPE *point,*p; + long h, w,n; + + if (!bgInitialized) return; + + point = (TYPE *)(canvasBuffer + clip_rect.ymin * bpl) + clip_rect.xmin*BPP; + w = clip_rect.xmax - clip_rect.xmin; + h = clip_rect.ymax - clip_rect.ymin; + + while (h--) { + p = point; + n = w; + while (n--) { + *p++ = backgroundColor.blue; + *p++ = backgroundColor.green; + *p++ = backgroundColor.red; + } + + point = (TYPE *)((char *)point + bpl); + } + + flashDisplay->flash_refresh = 1; + flashDisplay->clip_x = clip_rect.xmin; + flashDisplay->clip_y = clip_rect.ymin; + flashDisplay->clip_width = clip_rect.xmax-clip_rect.xmin; + flashDisplay->clip_height = clip_rect.ymax-clip_rect.ymin; +} + +/* alpha = 0 : select c1, alpha = 255 select c2 */ +static inline void mix_alpha(TYPE *c1, Color c2, int alpha) +{ + *c1 = (((c2.blue- (*c1))*alpha + (*c1) * 256) >> 8); + c1++; + *c1 = (((c2.green- (*c1))*alpha + (*c1) * 256) >> 8); + c1++; + *c1 = (((c2.red- (*c1))*alpha + (*c1) * 256) >> 8); +} + +void +GraphicDevice24::fillLineAA(FillStyleDef *f, long y, long start, long end) +{ + register long n; + TYPE *line; + TYPE *point; + Color pixel; + unsigned int alpha, start_alpha,end_alpha; + + if (clip(y,start,end)) return; + + line = (TYPE *)(canvasBuffer + bpl*y); + + alpha = f->color.alpha; + pixel = f->color; + + if (alpha == ALPHA_OPAQUE) { + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start >>= FRAC_BITS; + end >>= FRAC_BITS; + + point = &line[start*BPP]; + + if (start == end) { + mix_alpha(point, pixel, start_alpha + end_alpha - 255); + } else { + n = end-start; + if (start_alpha < 255) { + mix_alpha(point, pixel, start_alpha); + point += BPP; + n--; + } + while (n > 0) { + *point++ = pixel.blue; + *point++ = pixel.green; + *point++ = pixel.red; + n--; + } + if (end_alpha > 0) { + mix_alpha(point, pixel, end_alpha); + } + } + } else { + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start >>= FRAC_BITS; + end >>= FRAC_BITS; + + point = &line[start*BPP]; + + if (start == end) { + mix_alpha(point, pixel, ((start_alpha + end_alpha - 255) * alpha) >> 8); + } else { + n = end-start; + if (start_alpha < 255) { + mix_alpha(point, pixel, (start_alpha * alpha) >> 8); + point+=BPP; + n--; + } + while (n > 0) { + mix_alpha(point, pixel, alpha); + point+=BPP; + n--; + } + if (end_alpha > 0) { + mix_alpha(point, pixel, (end_alpha * alpha) >> 8); + } + } + } +} + +void +GraphicDevice24::fillLine(FillStyleDef *f, long y, long start, long end) +{ + register long n; + TYPE *line,*point; + Color pixel; + unsigned int alpha; + + if (clip(y,start,end)) return; + + start >>= FRAC_BITS; + end >>= FRAC_BITS; + + line = (TYPE *)(canvasBuffer + bpl*y); + point = &line[start*BPP]; + n = end-start; + alpha = f->color.alpha; + pixel = f->color; + if (alpha == ALPHA_OPAQUE) { + while (n--) { + *point++ = pixel.blue; + *point++ = pixel.green; + *point++ = pixel.red; + } + } else { + while (n--) { + mix_alpha(point, pixel, alpha); + point+=BPP; + } + } +} + +void +GraphicDevice24::fillLineBitmap(FillStyleDef *f, long y, long start, long end) +{ + int n; + long x1,y1,dx,dy; + Matrix *m = &f->bitmap_matrix; + Bitmap *b = f->bitmap; + unsigned char *pixels; + TYPE *p; + Color *cmap; + long pixbpl; + Color pixel; + int offset; + unsigned char *alpha_table; + + /* safety test) */ + if (!b) return; + + if (clip(y,start,end)) return; + + start /= FRAC; + end /= FRAC; + n = end - start; + p = (TYPE *) (canvasBuffer + bpl*y + start*BPP); + + x1 = (long) (m->a * start + m->b * y + m->tx); + y1 = (long) (m->c * start + m->d * y + m->ty); + dx = (long) (m->a); + dy = (long) (m->c); + + pixels = b->pixels; + pixbpl = b->bpl; + cmap = f->cmap; + + if (b->alpha_buf == NULL) { + while (n) { + if (x1 >= 0 && y1 >= 0 && + (x1 >> 16) < b->width && (y1 >> 16) < b->height) { + + pixel = cmap[pixels[(y1 >> 16) * pixbpl + (x1 >> 16)]]; + *p++ = pixel.blue; + *p++ = pixel.green; + *p++ = pixel.red; + } else { + p+=BPP; + } + x1 += dx; + y1 += dy; + n--; + } + } else if (f->alpha_table) { + alpha_table = f->alpha_table; + while (n) { + if (x1 >= 0 && y1 >= 0 && + (x1 >> 16) < b->width && (y1 >> 16) < b->height) { + + offset = (y1 >> 16) * pixbpl + (x1 >> 16); + mix_alpha(p, cmap[pixels[offset]], alpha_table[b->alpha_buf[offset]]); + } + p+=BPP; + x1 += dx; + y1 += dy; + n--; + } + } else { + while (n) { + if (x1 >= 0 && y1 >= 0 && + (x1 >> 16) < b->width && (y1 >> 16) < b->height) { + + offset = (y1 >> 16) * pixbpl + (x1 >> 16); + mix_alpha(p, cmap[pixels[offset]], b->alpha_buf[offset]); + } + p+=BPP; + x1 += dx; + y1 += dy; + n--; + } + } +} + +void +GraphicDevice24::fillLineLG(Gradient *grad, long y, long start, long end) +{ + long dr,r,v,r2; + register long n; + TYPE *line; + TYPE *point; + Color *cp,*ramp; + Matrix *m = &grad->imat; + unsigned int start_alpha,end_alpha; + + if (clip(y,start,end)) return; + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start /= FRAC; + end /= FRAC; + + n = end-start; + + r = (long) (m->a * start + m->b * y + m->tx); + dr = (long) (m->a); + + ramp = grad->ramp; + + line = (TYPE *)(canvasBuffer + bpl*y); + point = &line[start*BPP]; + + r2 = r + n * dr; + if ( ((r | r2) & ~255) == 0 ) { + if (!grad->has_alpha) { +#ifdef FULL_AA + if (start_alpha < 255) { + v = r>>16; + mix_alpha(point, ramp[v], start_alpha); + point+=BPP; + r += dr; + n--; + } +#endif /* FULL_AA */ + while (n>0) { + v = r>>16; + *point++ = ramp[v].blue; + *point++ = ramp[v].green; + *point++ = ramp[v].red; + r += dr; + n--; + } +#ifdef FULL_AA + if (end_alpha > 0) { + v = r>>16; + mix_alpha(point, ramp[v], end_alpha); + } +#endif /* FULL_AA */ + } else { + while (n--) { + v = r>>16; + cp = &ramp[v]; + mix_alpha(point, *cp, cp->alpha); + point+=BPP; + r += dr; + } + } + } else { + if (!grad->has_alpha) { +#ifdef FULL_AA + if (start_alpha < 255) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + mix_alpha(point, ramp[v], start_alpha); + point+=BPP; + r += dr; + n--; + } +#endif /* FULL_AA */ + while (n>0) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + *point++ = ramp[v].blue; + *point++ = ramp[v].green; + *point++ = ramp[v].red; + r += dr; + n--; + } +#ifdef FULL_AA + if (end_alpha > 0) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + mix_alpha(point, ramp[v], end_alpha); + } +#endif /* FULL_AA */ + } else { + while (n--) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + cp = &ramp[v]; + mix_alpha(point, *cp, cp->alpha); + point+=BPP; + r += dr; + } + } + } +} + +void +GraphicDevice24::fillLineRG(Gradient *grad, long y, long start, long end) +{ + long X,dx,r,Y,dy; + long dist2; + register long n; + Color *cp,*ramp; + TYPE *line; + TYPE *point; + Matrix *m = &grad->imat; + unsigned int start_alpha,end_alpha; + + if (clip(y,start,end)) return; + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start /= FRAC; + end /= FRAC; + + n = end-start; + + X = (long) (m->a * start + m->b * y + m->tx); + Y = (long) (m->c * start + m->d * y + m->ty); + dx = (long) (m->a); + dy = (long) (m->c); + + ramp = grad->ramp; + + line = (TYPE *)(canvasBuffer + bpl*y); + point = &line[start*BPP]; + + if (!grad->has_alpha) { +#ifdef FULL_AA + if (start == end) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r= SQRT[dist2]; + } + mix_alpha(point, ramp[r], start_alpha + end_alpha - 255); + } else { + if (start_alpha < 255) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r= SQRT[dist2]; + } + mix_alpha(point, ramp[r], start_alpha); + point+=BPP; + X += dx; + Y += dy; + n--; + } +#endif /* FULL_AA */ + while (n>0) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r= SQRT[dist2]; + } + *point++ = ramp[r].blue; + *point++ = ramp[r].green; + *point++ = ramp[r].red; + X += dx; + Y += dy; + n--; + } +#ifdef FULL_AA + if (end_alpha > 0) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r= SQRT[dist2]; + } + mix_alpha(point, ramp[r], end_alpha); + } + } +#endif /* FULL_AA */ + + } else { + while (n--) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r= SQRT[dist2]; + } + cp = &ramp[r]; + mix_alpha(point, *cp, cp->alpha); + point+=BPP; + X += dx; + Y += dy; + } + } +} + +void +GraphicDevice24::drawLine(long x1, long y1, long x2, long y2, long width) +{ + int n,adr,dx,dy,sx; + Color color; + register int a; + register TYPE *pp; + int alpha; + + x1 = (x1) >> FRAC_BITS; + y1 = (y1) >> FRAC_BITS; + x2 = (x2) >> FRAC_BITS; + y2 = (y2) >> FRAC_BITS; + + if (y1 > y2 || (y1 == y2 && x1 > x2)) { + long tmp; + + tmp=x1; + x1=x2; + x2=tmp; + + tmp=y1; + y1=y2; + y2=tmp; + } + + if (y1 == y2 && (y1 < clip_rect.ymin || y1 > clip_rect.ymax)) return; + if (x1 == x2 && (x1 < clip_rect.xmin || x1 > clip_rect.xmax)) return; + if (x1 == x2 && y1 == y2) return; // Bad !!! + + if (y1 < clip_rect.ymin && y1 != y2) { + x1 += (x2-x1)*(clip_rect.ymin-y1)/(y2-y1); + y1 = clip_rect.ymin; + } + + if (y2 > clip_rect.ymax && y1 != y2) { + x2 -= (x2-x1)*(y2-clip_rect.ymax)/(y2-y1); + y2 = clip_rect.ymax; + } + + if (x1 < x2) { + if (x1 < clip_rect.xmin && x1 != x2) { + y1 += (y2-y1)*(clip_rect.xmin-x1)/(x2-x1); + x1 = clip_rect.xmin; + } + + if (x2 > clip_rect.xmax && x1 != x2) { + y2 -= (y2-y1)*(x2-clip_rect.xmax)/(x2-x1); + x2 = clip_rect.xmax; + } + } + + if (x1 > x2) { + if (x2 < clip_rect.xmin && x2 != x1) { + y2 -= (y2-y1)*(clip_rect.xmin-x2)/(x1-x2); + x2 = clip_rect.xmin; + } + + if (x1 > clip_rect.xmax && x2 != x1) { + y1 += (y2-y1)*(x1-clip_rect.xmax)/(x1-x2); + x1 = clip_rect.xmax; + } + } + + // Check again + if (x1 == x2 && y1 == y2) return; + if (x1 < clip_rect.xmin || x2 < clip_rect.xmin) return; + if (y1 < clip_rect.ymin || y2 < clip_rect.ymin) return; + if (x1 > clip_rect.xmax || x2 > clip_rect.xmax) return; + if (y1 > clip_rect.ymax || y2 > clip_rect.ymax) return; + + sx=bpl >> 1; + adr=(y1 * sx + x1); + pp = (TYPE *)canvasBuffer + adr; + + dx = x2 - x1; + dy = y2 - y1; + + color = foregroundColor; + alpha = foregroundColor.alpha; + + if (alpha == ALPHA_OPAQUE) { + +#define PUTPIXEL() \ + { \ + *pp++=color.red; \ + *pp++=color.green; \ + *pp++=color.blue; \ + } + +#define DRAWLINE(dx,dy,inc_1,inc_2) \ + n=dx;\ + a=2*dy-dx;\ + dy=2*dy;\ + dx=2*dx-dy;\ + do {\ + PUTPIXEL();\ + if (a>0) { pp+=(inc_1); a-=dx; }\ + else { pp+=(inc_2); a+=dy; }\ + } while (--n >= 0); + +/* fin macro */ + + if (dx == 0 && dy == 0) { + PUTPIXEL(); + } else if (dx > 0) { + if (dx >= dy) { + DRAWLINE(dx, dy, sx + 1, 1); + } else { + DRAWLINE(dy, dx, sx + 1, sx); + } + } else { + dx = -dx; + if (dx >= dy) { + DRAWLINE(dx, dy, sx - 1, -1); + } else { + DRAWLINE(dy, dx, sx - 1, sx); + } + } + + +#undef DRAWLINE +#undef PUTPIXEL + } else { +#define PUTPIXEL() \ + { \ + mix_alpha(pp,color,alpha); \ + } + +#define DRAWLINE(dx,dy,inc_1,inc_2) \ + n=dx;\ + a=2*dy-dx;\ + dy=2*dy;\ + dx=2*dx-dy;\ + do {\ + PUTPIXEL();\ + if (a>0) { pp+=(inc_1*BPP); a-=dx; }\ + else { pp+=(inc_2*BPP); a+=dy; }\ + } while (--n >= 0); + +/* fin macro */ + + if (dx == 0 && dy == 0) { + PUTPIXEL(); + } else if (dx > 0) { + if (dx >= dy) { + DRAWLINE(dx, dy, sx + 1, 1); + } else { + DRAWLINE(dy, dx, sx + 1, sx); + } + } else { + dx = -dx; + if (dx >= dy) { + DRAWLINE(dx, dy, sx - 1, -1); + } else { + DRAWLINE(dy, dx, sx - 1, sx); + } + } + + +#undef DRAWLINE +#undef PUTPIXEL + } +} diff --git a/core/multimedia/opieplayer/libflash/graphic24.h b/core/multimedia/opieplayer/libflash/graphic24.h new file mode 100644 index 0000000..4c10e49 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/graphic24.h @@ -0,0 +1,39 @@ +//////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +class GraphicDevice24: public GraphicDevice { +private: + long GraphicDevice24::allocColor(Color color); + +public: + GraphicDevice24(FlashDisplay *fd); + + void clearCanvas(); + void fillLineAA(FillStyleDef *f, long y, long start, long end); + void fillLine(FillStyleDef *f, long y, long start, long end); + void fillLineBitmap(FillStyleDef *f, long y, long start, long end); + void fillLineLG(Gradient *grad, long y, long start, long end); + void fillLineRG(Gradient *grad, long y, long start, long end); + void drawLine(long x1, long y1, long x2, long y2, long width); +}; diff --git a/core/multimedia/opieplayer/libflash/graphic32.cc b/core/multimedia/opieplayer/libflash/graphic32.cc new file mode 100644 index 0000000..b9c2008 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/graphic32.cc @@ -0,0 +1,657 @@ +//////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#include "graphic32.h" + +extern unsigned char SQRT[]; + +#define FULL_AA + +#define PRINT 0 + +typedef unsigned long TYPE; + +GraphicDevice32::GraphicDevice32(FlashDisplay *fd) : GraphicDevice(fd) +{ +} + +long +GraphicDevice32::allocColor(Color color) +{ + return (color.red)<<16 | (color.green)<<8 | (color.blue); +} + +void +GraphicDevice32::clearCanvas() +{ + TYPE pixel; + TYPE *point,*p; + long h, w,n; + + if (!bgInitialized) return; + + pixel = allocColor(backgroundColor); + + point = (TYPE *)(canvasBuffer + clip_rect.ymin * bpl) + clip_rect.xmin; + w = clip_rect.xmax - clip_rect.xmin; + h = clip_rect.ymax - clip_rect.ymin; + + while (h--) { + p = point; + n = w; + while (n--) { + *p++ = pixel; + } + + point = (TYPE *)((char *)point + bpl); + } + + flashDisplay->flash_refresh = 1; + flashDisplay->clip_x = clip_rect.xmin; + flashDisplay->clip_y = clip_rect.ymin; + flashDisplay->clip_width = clip_rect.xmax-clip_rect.xmin; + flashDisplay->clip_height = clip_rect.ymax-clip_rect.ymin; +} + +#define RED_MASK 0xFF0000 +#define GREEN_MASK 0x00FF00 +#define BLUE_MASK 0x0000FF + +/* alpha = 0 : select c1, alpha = 255 select c2 */ +static inline unsigned long +mix_alpha(unsigned long c1, unsigned long c2, int alpha) +{ + long r1,r2,r; + long g1,g2,g; + long b1,b2,b; + + r1 = c1 & RED_MASK; + r2 = c2 & RED_MASK; + r = (((r2-r1)*alpha + r1 * 256) >> 8) & RED_MASK; + + g1 = c1 & GREEN_MASK; + g2 = c2 & GREEN_MASK; + g = (((g2-g1)*alpha + g1 * 256) >> 8) & GREEN_MASK; + + b1 = c1 & BLUE_MASK; + b2 = c2 & BLUE_MASK; + b = (((b2-b1)*alpha + b1 * 256) >> 8) & BLUE_MASK; + + return (r|g|b); +} + +void +GraphicDevice32::fillLineAA(FillStyleDef *f, long y, long start, long end) +{ + register long n; + TYPE *line; + TYPE *point,pixel; + unsigned int alpha, start_alpha,end_alpha; + + if (clip(y,start,end)) return; + + line = (TYPE *)(canvasBuffer + bpl*y); + + alpha = f->color.alpha; + pixel = f->color.pixel; + + if (alpha == ALPHA_OPAQUE) { + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start >>= FRAC_BITS; + end >>= FRAC_BITS; + + point = &line[start]; + + if (start == end) { + *point = mix_alpha(*point, pixel, start_alpha + end_alpha - 255); + } else { + n = end-start; + if (start_alpha < 255) { + *point = mix_alpha(*point, pixel, start_alpha); + point++; + n--; + } + while (n > 0) { + *point = pixel; + point++; + n--; + } + if (end_alpha > 0) { + *point = mix_alpha(*point, pixel, end_alpha); + } + } + } else { + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start >>= FRAC_BITS; + end >>= FRAC_BITS; + + point = &line[start]; + + if (start == end) { + *point = mix_alpha(*point, pixel, + ((start_alpha + end_alpha - 255) * alpha) >> 8); + } else { + n = end-start; + if (start_alpha < 255) { + *point = mix_alpha(*point, pixel, (start_alpha * alpha) >> 8); + point++; + n--; + } + while (n > 0) { + *point = mix_alpha(*point, pixel, alpha); + point++; + n--; + } + if (end_alpha > 0) { + *point = mix_alpha(*point, pixel, (end_alpha * alpha) >> 8); + } + } + } +} + +void +GraphicDevice32::fillLine(FillStyleDef *f, long y, long start, long end) +{ + register long n; + TYPE *line,*point; + TYPE pixel; + unsigned int alpha; + + if (clip(y,start,end)) return; + + start >>= FRAC_BITS; + end >>= FRAC_BITS; + + line = (TYPE *)(canvasBuffer + bpl*y); + point = &line[start]; + n = end-start; + pixel = f->color.pixel; + alpha = f->color.alpha; + if (alpha == ALPHA_OPAQUE) { + while (n--) { + *point = pixel; + point++; + } + } else { + while (n--) { + *point = mix_alpha(*point, pixel, alpha); + point++; + } + } +} + +void +GraphicDevice32::fillLineBitmap(FillStyleDef *f, long y, long start, long end) +{ + int n; + long x1,y1,dx,dy; + Matrix *m = &f->bitmap_matrix; + Bitmap *b = f->bitmap; + unsigned char *pixels; + TYPE *p; + Color *cmap; + long pixbpl; + TYPE pixel; + int offset; + unsigned char *alpha_table; + + /* safety test) */ + if (!b) return; + + if (clip(y,start,end)) return; + + start /= FRAC; + end /= FRAC; + n = end - start; + p = (TYPE *) (this->canvasBuffer + this->bpl*y + start * sizeof(TYPE)); + + /* the coordinates in the image are normalized to 16 bits */ + x1 = (long) (m->a * start + m->b * y + m->tx); + y1 = (long) (m->c * start + m->d * y + m->ty); + dx = (long) (m->a); + dy = (long) (m->c); + + pixels = b->pixels; + pixbpl = b->bpl; + cmap = f->cmap; + + if (b->alpha_buf == NULL) { + while (n) { + if (x1 >= 0 && y1 >= 0 && + (x1 >> 16) < b->width && (y1 >> 16) < b->height) { + + pixel = cmap[pixels[(y1 >> 16) * pixbpl + (x1 >> 16)]].pixel; + *p = pixel; + } + x1 += dx; + y1 += dy; + p++; + n--; + } + } else if (f->alpha_table) { + alpha_table = f->alpha_table; + while (n) { + if (x1 >= 0 && y1 >= 0 && + (x1 >> 16) < b->width && (y1 >> 16) < b->height) { + + offset = (y1 >> 16) * pixbpl + (x1 >> 16); + pixel = cmap[pixels[offset]].pixel; + *p = mix_alpha(*p, pixel, alpha_table[b->alpha_buf[offset]]); + } + x1 += dx; + y1 += dy; + p++; + n--; + } + } else { + while (n) { + if (x1 >= 0 && y1 >= 0 && + (x1 >> 16) < b->width && (y1 >> 16) < b->height) { + + offset = (y1 >> 16) * pixbpl + (x1 >> 16); + pixel = cmap[pixels[offset]].pixel; + *p = mix_alpha(*p, pixel, b->alpha_buf[offset]); + } + x1 += dx; + y1 += dy; + p++; + n--; + } + } +} + +void +GraphicDevice32::fillLineLG(Gradient *grad, long y, long start, long end) +{ + long dr,r,v,r2; + register long n; + TYPE *line; + TYPE *point; + Color *cp,*ramp; + Matrix *m = &grad->imat; + unsigned int start_alpha,end_alpha; + + if (clip(y,start,end)) return; + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start /= FRAC; + end /= FRAC; + + n = end-start; + + r = (long) (m->a * start + m->b * y + m->tx); + dr = (long) (m->a); + + ramp = grad->ramp; + + line = (TYPE *)(canvasBuffer + bpl*y); + point = &line[start]; + + r2 = r + n * dr; + if ( ((r | r2) & ~255) == 0 ) { + if (!grad->has_alpha) { +#ifdef FULL_AA + if (start_alpha < 255) { + v = r>>16; + *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha); + point++; + r += dr; + n--; + } +#endif /* FULL_AA */ + while (n>0) { + v = r>>16; + *point = (TYPE)ramp[v].pixel; + point++; + r += dr; + n--; + } +#ifdef FULL_AA + if (end_alpha > 0) { + v = r>>16; + *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha); + } +#endif /* FULL_AA */ + } else { + while (n--) { + v = r>>16; + cp = &ramp[v]; + *point = mix_alpha(*point, cp->pixel, cp->alpha); + point++; + r += dr; + } + } + } else { + if (!grad->has_alpha) { +#ifdef FULL_AA + if (start_alpha < 255) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha); + point++; + r += dr; + n--; + } +#endif /* FULL_AA */ + while (n>0) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + *point = (TYPE)ramp[v].pixel; + point++; + r += dr; + n--; + } +#ifdef FULL_AA + if (end_alpha > 0) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha); + } +#endif /* FULL_AA */ + } else { + while (n--) { + v = r>>16; + if (v < 0) v = 0; + else if (v > 255) v = 255; + cp = &ramp[v]; + *point = mix_alpha(*point, cp->pixel, cp->alpha); + point++; + r += dr; + } + } + } +} + +void +GraphicDevice32::fillLineRG(Gradient *grad, long y, long start, long end) +{ + long X,dx,r,Y,dy; + long dist2; + register long n; + Color *cp,*ramp; + TYPE *line; + TYPE *point; + Matrix *m = &grad->imat; + unsigned int start_alpha,end_alpha; + + if (clip(y,start,end)) return; + + start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); + end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); + + start /= FRAC; + end /= FRAC; + + n = end-start; + + X = (long) (m->a * start + m->b * y + m->tx); + Y = (long) (m->c * start + m->d * y + m->ty); + dx = (long) (m->a); + dy = (long) (m->c); + + ramp = grad->ramp; + + line = (TYPE *)(canvasBuffer + bpl*y); + point = &line[start]; + + if (!grad->has_alpha) { +#ifdef FULL_AA + if (start == end) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r = SQRT[dist2]; + } + *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha + end_alpha - 255); + } else { + if (start_alpha < 255) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r = SQRT[dist2]; + } + *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha); + point++; + X += dx; + Y += dy; + n--; + } +#endif /* FULL_AA */ + while (n>0) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r= SQRT[dist2]; + } + *point = (TYPE)ramp[r].pixel; + point++; + X += dx; + Y += dy; + n--; + } +#ifdef FULL_AA + if (end_alpha > 0) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r= SQRT[dist2]; + } + *point = mix_alpha(*point, (TYPE)ramp[r].pixel, end_alpha); + } + } +#endif /* FULL_AA */ + + } else { + while (n--) { + dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); + if ((unsigned long)dist2 >= 65536) { + r = 255; + } else { + r= SQRT[dist2]; + } + cp = &ramp[r]; + *point = mix_alpha(*point, cp->pixel, cp->alpha); + point++; + X += dx; + Y += dy; + } + } +} + +void +GraphicDevice32::drawLine(long x1, long y1, long x2, long y2, long width) +{ + int n,adr,dx,dy,sx,color; + register int a; + register TYPE *pp; + int alpha; + + x1 = (x1) >> FRAC_BITS; + y1 = (y1) >> FRAC_BITS; + x2 = (x2) >> FRAC_BITS; + y2 = (y2) >> FRAC_BITS; + + if (y1 > y2 || (y1 == y2 && x1 > x2)) { + long tmp; + + tmp=x1; + x1=x2; + x2=tmp; + + tmp=y1; + y1=y2; + y2=tmp; + } + + if (y1 == y2 && (y1 < clip_rect.ymin || y1 > clip_rect.ymax)) return; + if (x1 == x2 && (x1 < clip_rect.xmin || x1 > clip_rect.xmax)) return; + if (x1 == x2 && y1 == y2) return; // Bad !!! + + if (y1 < clip_rect.ymin && y1 != y2) { + x1 += (x2-x1)*(clip_rect.ymin-y1)/(y2-y1); + y1 = clip_rect.ymin; + } + + if (y2 > clip_rect.ymax && y1 != y2) { + x2 -= (x2-x1)*(y2-clip_rect.ymax)/(y2-y1); + y2 = clip_rect.ymax; + } + + if (x1 < x2) { + if (x1 < clip_rect.xmin && x1 != x2) { + y1 += (y2-y1)*(clip_rect.xmin-x1)/(x2-x1); + x1 = clip_rect.xmin; + } + + if (x2 > clip_rect.xmax && x1 != x2) { + y2 -= (y2-y1)*(x2-clip_rect.xmax)/(x2-x1); + x2 = clip_rect.xmax; + } + } + + if (x1 > x2) { + if (x2 < clip_rect.xmin && x2 != x1) { + y2 -= (y2-y1)*(clip_rect.xmin-x2)/(x1-x2); + x2 = clip_rect.xmin; + } + + if (x1 > clip_rect.xmax && x2 != x1) { + y1 += (y2-y1)*(x1-clip_rect.xmax)/(x1-x2); + x1 = clip_rect.xmax; + } + } + + // Check again + if (x1 == x2 && y1 == y2) return; + if (x1 < clip_rect.xmin || x2 < clip_rect.xmin) return; + if (y1 < clip_rect.ymin || y2 < clip_rect.ymin) return; + if (x1 > clip_rect.xmax || x2 > clip_rect.xmax) return; + if (y1 > clip_rect.ymax || y2 > clip_rect.ymax) return; + + sx=bpl >> 1; + adr=(y1 * sx + x1); + pp = (TYPE *)canvasBuffer + adr; + + dx = x2 - x1; + dy = y2 - y1; + + color = allocColor(foregroundColor); + alpha = foregroundColor.alpha; + + if (alpha == ALPHA_OPAQUE) { + +#define PUTPIXEL() \ + { \ + *pp=color; \ + } + +#define DRAWLINE(dx,dy,inc_1,inc_2) \ + n=dx;\ + a=2*dy-dx;\ + dy=2*dy;\ + dx=2*dx-dy;\ + do {\ + PUTPIXEL();\ + if (a>0) { pp+=(inc_1); a-=dx; }\ + else { pp+=(inc_2); a+=dy; }\ + } while (--n >= 0); + +/* fin macro */ + + if (dx == 0 && dy == 0) { + PUTPIXEL(); + } else if (dx > 0) { + if (dx >= dy) { + DRAWLINE(dx, dy, sx + 1, 1); + } else { + DRAWLINE(dy, dx, sx + 1, sx); + } + } else { + dx = -dx; + if (dx >= dy) { + DRAWLINE(dx, dy, sx - 1, -1); + } else { + DRAWLINE(dy, dx, sx - 1, sx); + } + } + + +#undef DRAWLINE +#undef PUTPIXEL + } else { +#define PUTPIXEL() \ + { \ + *pp=mix_alpha(*pp,color,alpha); \ + } + +#define DRAWLINE(dx,dy,inc_1,inc_2) \ + n=dx;\ + a=2*dy-dx;\ + dy=2*dy;\ + dx=2*dx-dy;\ + do {\ + PUTPIXEL();\ + if (a>0) { pp+=(inc_1); a-=dx; }\ + else { pp+=(inc_2); a+=dy; }\ + } while (--n >= 0); + +/* fin macro */ + + if (dx == 0 && dy == 0) { + PUTPIXEL(); + } else if (dx > 0) { + if (dx >= dy) { + DRAWLINE(dx, dy, sx + 1, 1); + } else { + DRAWLINE(dy, dx, sx + 1, sx); + } + } else { + dx = -dx; + if (dx >= dy) { + DRAWLINE(dx, dy, sx - 1, -1); + } else { + DRAWLINE(dy, dx, sx - 1, sx); + } + } + + +#undef DRAWLINE +#undef PUTPIXEL + } +} diff --git a/core/multimedia/opieplayer/libflash/graphic32.h b/core/multimedia/opieplayer/libflash/graphic32.h new file mode 100644 index 0000000..3d75a4d --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/graphic32.h @@ -0,0 +1,39 @@ +//////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +class GraphicDevice32: public GraphicDevice { +private: + long GraphicDevice32::allocColor(Color color); + +public: + GraphicDevice32(FlashDisplay *fd); + + void clearCanvas(); + void fillLineAA(FillStyleDef *f, long y, long start, long end); + void fillLine(FillStyleDef *f, long y, long start, long end); + void fillLineBitmap(FillStyleDef *f, long y, long start, long end); + void fillLineLG(Gradient *grad, long y, long start, long end); + void fillLineRG(Gradient *grad, long y, long start, long end); + void drawLine(long x1, long y1, long x2, long y2, long width); +}; diff --git a/core/multimedia/opieplayer/libflash/jconfig.h b/core/multimedia/opieplayer/libflash/jconfig.h new file mode 100644 index 0000000..9594ec5 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/jconfig.h @@ -0,0 +1,45 @@ +/* jconfig.h. Generated automatically by configure. */ +/* jconfig.cfg --- source file edited by configure script */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +#undef void +#undef const +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS +#undef NEED_SHORT_EXTERNAL_NAMES +/* Define this if you get warnings about undefined structures. */ +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED +#define INLINE __inline__ +/* These are for configuring the JPEG memory manager. */ +#undef DEFAULT_MAX_MEM +#undef NO_MKTEMP + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#undef TWO_FILE_COMMANDLINE +#undef NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. */ +#undef PROGRESS_REPORT + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/core/multimedia/opieplayer/libflash/jerror.h b/core/multimedia/opieplayer/libflash/jerror.h new file mode 100644 index 0000000..fc2fffe --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/jerror.h @@ -0,0 +1,291 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_ARITH_NOTIMPL, + "Sorry, there are legal restrictions on arithmetic coding") +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/core/multimedia/opieplayer/libflash/jmorecfg.h b/core/multimedia/opieplayer/libflash/jmorecfg.h new file mode 100644 index 0000000..54a7d1c --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/jmorecfg.h @@ -0,0 +1,363 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +typedef long INT32; +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/core/multimedia/opieplayer/libflash/jpeglib.h b/core/multimedia/opieplayer/libflash/jpeglib.h new file mode 100644 index 0000000..d1be8dd --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/jpeglib.h @@ -0,0 +1,1096 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ + +#define JPEG_LIB_VERSION 62 /* Version 6b */ + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples. Always DCTSIZE for compression. + * For decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values of 1,2,4,8 are likely to be supported. Note that different + * components may receive different IDCT scalings. + */ + int DCT_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For decompression, IDCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.doc concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#endif /* JPEGLIB_H */ diff --git a/core/multimedia/opieplayer/libflash/libflash.pro b/core/multimedia/opieplayer/libflash/libflash.pro new file mode 100644 index 0000000..d144f0b --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/libflash.pro @@ -0,0 +1,15 @@ +TEMPLATE = lib +CONFIG += qt warn_on release +HEADERS = libflashplugin.h libflashpluginimpl.h +SOURCES = libflashplugin.cpp libflashpluginimpl.cpp \ + adpcm.cc character.cc flash.cc graphic16.cc matrix.cc script.cc \ + sprite.cc bitmap.cc cxform.cc font.cc graphic24.cc movie.cc \ + shape.cc sqrt.cc button.cc displaylist.cc graphic.cc graphic32.cc \ + program.cc sound.cc text.cc +TARGET = flashplugin +DESTDIR = ../../plugins/codecs +INCLUDEPATH += $(QPEDIR)/include .. +DEPENDPATH += ../$(QPEDIR)/include .. +LIBS += -lqpe +VERSION = 1.0.0 + diff --git a/core/multimedia/opieplayer/libflash/libflashplugin.cpp b/core/multimedia/opieplayer/libflash/libflashplugin.cpp new file mode 100644 index 0000000..538c695 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/libflashplugin.cpp @@ -0,0 +1,223 @@ +/********************************************************************** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "libflashplugin.h" + +#if 0 + +bool LibFlashPlugin::audioReadSamples( short *output, int channel, long samples, int stream ) { +} + + +bool LibFlashPlugin::audioReReadSamples( short *output, int channel, long samples, int stream ) { +} + + +bool LibFlashPlugin::audioReadMonoSamples( short *output, long samples, long& samplesRead, int stream ) { + samplesRead = samples; +} + + +bool LibFlashPlugin::audioReadStereoSamples( short *output, long samples, long& samplesRead, int stream ) { +} + + +bool LibFlashPlugin::videoReadFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, ColorFormat color_model, int stream ) { +} + + +bool LibFlashPlugin::videoReadScaledFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, ColorFormat color_model, int stream ) { +/* + int format = MPEG3_RGB565; + switch ( color_model ) { + case RGB565: format = MPEG3_RGB565; break; + case RGBA8888: format = MPEG3_RGBA8888; break; + case BGRA8888: format = MPEG3_BGRA8888; break; + } +*/ +} + + +bool LibFlashPlugin::videoReadYUVFrame( char *y_output, char *u_output, char *v_output, int in_x, int in_y, int in_w, int in_h, int stream ) { +} + + +FlashHandle file; +FlashDisplay *fd; + +#endif + + +LibFlashPlugin::LibFlashPlugin() { + file = NULL; + fd = 0; +} +#include +#include +static int readFile(const char *filename, char **buffer, long *size) +{ + FILE *in; + char *buf; + long length; + + printf("read files\n"); + + in = fopen(filename,"r"); + if (in == 0) { + perror(filename); + return -1; + } + fseek(in,0,SEEK_END); + length = ftell(in); + rewind(in); + buf = (char *)malloc(length); + fread(buf,length,1,in); + fclose(in); + + *size = length; + *buffer = buf; + + return length; +} + +static void showUrl(char *url, char * /*target*/, void * /*client_data*/) { + printf("get url\n"); + printf("GetURL : %s\n", url); +} + +static void getSwf(char *url, int level, void *client_data) { + FlashHandle flashHandle = (FlashHandle) client_data; + char *buffer; + long size; + + printf("get swf\n"); + + printf("LoadMovie: %s @ %d\n", url, level); + if (readFile(url, &buffer, &size) > 0) { + FlashParse(flashHandle, level, buffer, size); + } +} + +bool LibFlashPlugin::open( const QString& fileName ) { + + printf("opening file\n"); + + delete fd; + fd = new FlashDisplay; + fd->pixels = new int[320*240*4]; + fd->width = 200; + fd->bpl = 320*2; + fd->height = 300; + fd->depth = 16; + fd->bpp = 2; + fd->flash_refresh = 25; + fd->clip_x = 0; + fd->clip_y = 0; + fd->clip_width = 0; + fd->clip_height = 0; + + char *buffer; + long size; + int status; + struct FlashInfo fi; + + if (readFile(fileName.latin1(), &buffer, &size) < 0) + exit(2); + + if (!(file = FlashNew())) + exit(1); + + do + status = FlashParse(file, 0, buffer, size); + while (status & FLASH_PARSE_NEED_DATA); + + free(buffer); + FlashGetInfo(file, &fi); + //FlashSettings(flashHandle, PLAYER_LOOP); + FlashGraphicInit(file, fd); + FlashSoundInit(file, "/dev/dsp"); + FlashSetGetUrlMethod(file, showUrl, 0); + FlashSetGetSwfMethod(file, getSwf, (void*)file); + + printf("opened file\n"); +} + +// If decoder doesn't support audio then return 0 here +bool LibFlashPlugin::audioSetSample( long sample, int stream ) { return TRUE; } +long LibFlashPlugin::audioGetSample( int stream ) { return 0; } +//bool LibFlashPlugin::audioReadMonoSamples( short *output, long samples, long& samplesRead, int stream ) { return TRUE; } +//bool LibFlashPlugin::audioReadStereoSamples( short *output, long samples, long& samplesRead, int stream ) { return FALSE; } +bool LibFlashPlugin::audioReadSamples( short *output, int channels, long samples, long& samplesRead, int stream ) { return FALSE; } +//bool LibFlashPlugin::audioReadSamples( short *output, int channel, long samples, int stream ) { return TRUE; } +//bool LibFlashPlugin::audioReReadSamples( short *output, int channel, long samples, int stream ) { return TRUE; } + +// If decoder doesn't support video then return 0 here +int LibFlashPlugin::videoStreams() { return 1; } +int LibFlashPlugin::videoWidth( int stream ) { return 300; } +int LibFlashPlugin::videoHeight( int stream ) { return 200; } +double LibFlashPlugin::videoFrameRate( int stream ) { return 25.0; } +int LibFlashPlugin::videoFrames( int stream ) { return 1000000; } +bool LibFlashPlugin::videoSetFrame( long frame, int stream ) { return TRUE; } +long LibFlashPlugin::videoGetFrame( int stream ) { return 0; } +bool LibFlashPlugin::videoReadFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, ColorFormat color_model, int stream ) { return TRUE; } +#include +bool LibFlashPlugin::videoReadScaledFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, ColorFormat color_model, int stream ) { + struct timeval wd; + FlashEvent fe; + +/* + delete fd; + fd = new FlashDisplay; + fd->pixels = output_rows[0]; + fd->width = 300; // out_w; + fd->bpl = 640; // out_w*2; + fd->height = 200;//out_h; + fd->depth = 16; + fd->bpp = 2; + fd->flash_refresh = 50; + fd->clip_x = 0;//in_x; + fd->clip_y = 0;//in_y; + fd->clip_width = 300;//in_w; + fd->clip_height = 200;//in_h; + FlashGraphicInit(file, fd); +*/ + + long cmd = FLASH_WAKEUP; + FlashExec(file, cmd, 0, &wd); + + fe.type = FeRefresh; + cmd = FLASH_EVENT; + FlashExec(file, cmd, &fe, &wd); +/* + for (int i = 0; i < out_h; i++) + memcpy( output_rows[i], (char*)fd->pixels + i*fd->bpl, QMIN( fd->width * fd->bpp, out_w * fd->bpp ) ); +*/ + memcpy( output_rows[0], (char*)fd->pixels, out_w * out_h * 2 ); +} + +bool LibFlashPlugin::videoReadYUVFrame( char *y_output, char *u_output, char *v_output, int in_x, int in_y, int in_w, int in_h, int stream ) { return TRUE; } + +// Profiling +double LibFlashPlugin::getTime() { return 0.0; } + +// Ignore if these aren't supported +bool LibFlashPlugin::setSMP( int cpus ) { return TRUE; } +bool LibFlashPlugin::setMMX( bool useMMX ) { return TRUE; } + + diff --git a/core/multimedia/opieplayer/libflash/libflashplugin.h b/core/multimedia/opieplayer/libflash/libflashplugin.h new file mode 100644 index 0000000..532bca2 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/libflashplugin.h @@ -0,0 +1,96 @@ +/********************************************************************** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef LIBFLASH_PLUGIN_H +#define LIBFLASH_PLUGIN_H + + +#include +#include +#include "flash.h" +#include "mediaplayerplugininterface.h" + + +class LibFlashPlugin : public MediaPlayerDecoder { + +public: + LibFlashPlugin(); + ~LibFlashPlugin() { close(); } + + const char *pluginName() { return "LibFlashPlugin: " PLUGIN_NAME " " FLASH_VERSION_STRING; } + const char *pluginComment() { return "This is the libflash library: " PLUGIN_NAME " " FLASH_VERSION_STRING; } + double pluginVersion() { return 1.0; } + + bool isFileSupported( const QString& fileName ) { return fileName.right(4) == ".swf"; } + bool open( const QString& fileName ); + bool close() { FlashClose( file ); file = NULL; return TRUE; } + bool isOpen() { return file != NULL; } + const QString &fileInfo() { return strInfo = qApp->translate( "MediaPlayer", "No Information Available", "media plugin text" ); } + + // If decoder doesn't support audio then return 0 here + int audioStreams() { return 1; } + int audioChannels( int /*stream*/ ) { return 2; } + int audioFrequency( int /*stream*/ ) { return 44100; } + int audioSamples( int /*stream*/ ) { return 1000000; } + bool audioSetSample( long sample, int stream ); + long audioGetSample( int stream ); + //bool audioReadMonoSamples( short *output, long samples, long& samplesRead, int stream ); + //bool audioReadStereoSamples( short *output, long samples, long& samplesRead, int stream ); + bool audioReadSamples( short *output, int channels, long samples, long& samplesRead, int stream ); + //bool audioReadSamples( short *output, int channel, long samples, int stream ); + //bool audioReReadSamples( short *output, int channel, long samples, int stream ); + + // If decoder doesn't support video then return 0 here + int videoStreams(); + int videoWidth( int stream ); + int videoHeight( int stream ); + double videoFrameRate( int stream ); + int videoFrames( int stream ); + bool videoSetFrame( long frame, int stream ); + long videoGetFrame( int stream ); + bool videoReadFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, ColorFormat color_model, int stream ); + bool videoReadScaledFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, ColorFormat color_model, int stream ); + bool videoReadYUVFrame( char *y_output, char *u_output, char *v_output, int in_x, int in_y, int in_w, int in_h, int stream ); + + // Profiling + double getTime(); + + // Ignore if these aren't supported + bool setSMP( int cpus ); + bool setMMX( bool useMMX ); + + // Capabilities + bool supportsAudio() { return TRUE; } + bool supportsVideo() { return TRUE; } + bool supportsYUV() { return TRUE; } + bool supportsMMX() { return TRUE; } + bool supportsSMP() { return TRUE; } + bool supportsStereo() { return TRUE; } + bool supportsScaling() { return TRUE; } + +private: + FlashHandle file; + FlashDisplay *fd; + QString strInfo; + +}; + + +#endif + diff --git a/core/multimedia/opieplayer/libflash/libflashpluginimpl.cpp b/core/multimedia/opieplayer/libflash/libflashpluginimpl.cpp new file mode 100644 index 0000000..af2c07e --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/libflashpluginimpl.cpp @@ -0,0 +1,70 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "libflashplugin.h" +#include "libflashpluginimpl.h" + + +LibFlashPluginImpl::LibFlashPluginImpl() + : libflashplugin(0), ref(0) +{ +} + + +LibFlashPluginImpl::~LibFlashPluginImpl() +{ + if ( libflashplugin ) + delete libflashplugin; +} + + +MediaPlayerDecoder *LibFlashPluginImpl::decoder() +{ + if ( !libflashplugin ) + libflashplugin = new LibFlashPlugin; + return libflashplugin; +} + + +MediaPlayerEncoder *LibFlashPluginImpl::encoder() +{ + return NULL; +} + + +#ifndef QT_NO_COMPONENT + + +QRESULT LibFlashPluginImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ + *iface = 0; + if ( ( uuid == IID_QUnknown ) || ( uuid == IID_MediaPlayerPlugin ) ) + *iface = this, (*iface)->addRef(); + return QS_OK; +} + + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( LibFlashPluginImpl ) +} + + +#endif + diff --git a/core/multimedia/opieplayer/libflash/libflashpluginimpl.h b/core/multimedia/opieplayer/libflash/libflashpluginimpl.h new file mode 100644 index 0000000..b5cc869 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/libflashpluginimpl.h @@ -0,0 +1,53 @@ +/********************************************************************** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef LIBFLASH_PLUGIN_IMPL_H +#define LIBFLASH_PLUGIN_IMPL_H + + +#include "../mediaplayerplugininterface.h" + + +class LibFlashPlugin; + + +class LibFlashPluginImpl : public MediaPlayerPluginInterface +{ +public: + LibFlashPluginImpl(); + virtual ~LibFlashPluginImpl(); + +#ifndef QT_NO_COMPONENT + + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT + +#endif + + virtual MediaPlayerDecoder *decoder(); + virtual MediaPlayerEncoder *encoder(); + +private: + LibFlashPlugin *libflashplugin; + ulong ref; +}; + + +#endif + diff --git a/core/multimedia/opieplayer/libflash/matrix.cc b/core/multimedia/opieplayer/libflash/matrix.cc new file mode 100644 index 0000000..0d8c82c --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/matrix.cc @@ -0,0 +1,68 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "matrix.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +Matrix::Matrix() +{ + a = 1.0; + d = 1.0; + b = c = 0.0; + tx = ty = 0; +} + +Matrix Matrix::operator*(Matrix m) +{ + Matrix mat; + + mat.a = this->a * m.a + this->b * m.c; + mat.b = this->a * m.b + this->b * m.d; + mat.c = this->c * m.a + this->d * m.c; + mat.d = this->c * m.b + this->d * m.d; + + mat.tx = this->getX(m.tx,m.ty); + mat.ty = this->getY(m.tx,m.ty); + + return mat; +} + +Matrix Matrix::invert() +{ + Matrix mat; + float det; + + det = a*d-b*c; + + mat.a = d/det; + mat.b = -b/det; + mat.c = -c/det; + mat.d = a/det; + + mat.tx = - (long)(mat.a * tx + mat.b * ty); + mat.ty = - (long)(mat.c * tx + mat.d * ty); + + return mat; +} diff --git a/core/multimedia/opieplayer/libflash/matrix.h b/core/multimedia/opieplayer/libflash/matrix.h new file mode 100644 index 0000000..83b54c2 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/matrix.h @@ -0,0 +1,49 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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 _MATRIX_H_ +#define _MATRIX_H_ + +struct Matrix { + float a,b,c,d; + long tx,ty; +public: + Matrix operator*(Matrix); + Matrix invert(); + Matrix(); + +#ifdef DUMP + void dump(BitStream *bs); +#endif + + inline + long Matrix::getX(long x, long y) + { + return (long) (x*a+y*b+tx); + }; + + inline + long Matrix::getY(long x, long y) + { + return (long) (x*c+y*d+ty); + }; + +}; + +#endif /* _MATRIX_H_ */ diff --git a/core/multimedia/opieplayer/libflash/movie.cc b/core/multimedia/opieplayer/libflash/movie.cc new file mode 100644 index 0000000..349e43b --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/movie.cc @@ -0,0 +1,171 @@ +//////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// +#include "movie.h" + +FlashMovie::FlashMovie() +{ + gd = NULL; + sm = NULL; + getSwf = NULL; + getUrl = NULL; + cursorOnOff = NULL; + buttons_updated = 0; + scheduledTime.tv_sec = -1; + cur_focus = NULL; + lost_over = NULL; + msPerFrame = 0; + + /* mouse handling */ + mouse_active = 0; + mouse_x = -1; + mouse_y = -1; + button_pressed = 0; + refresh = 1; +} + +FlashMovie::~FlashMovie() +{ + CInputScript *n; + + while (main != NULL) { + n = main->next; + delete main; + main = n; + } + + if (gd) delete gd; + if (sm) delete sm; +} + +int +FlashMovie::processMovie(GraphicDevice *gd, SoundMixer *sm) +{ + CInputScript *script; + int wakeUp = 0; + + if (sm && sm->playSounds()) { + wakeUp = 1; + } + for (script = this->main; script != NULL; script = script->next) { + if (script->program == NULL) continue; + if (script->program->nbFrames == 0) continue; + if (script->program->processMovie(gd,sm)) { + wakeUp = 1; + } + } + renderMovie(); + return wakeUp; +} + +int +FlashMovie::handleEvent(GraphicDevice *gd, SoundMixer *sm, FlashEvent *event) +{ + int wakeUp = 0; + + if (sm && sm->playSounds()) { + wakeUp = 1; + } + if (this->main == 0) return 0; + if (this->main->program == 0) return 0; + if (this->main->program->handleEvent(gd, sm, event)) { + wakeUp = 1; + } + renderMovie(); + return wakeUp; +} + +/* current focus bigger and translated if needed */ +void +FlashMovie::renderFocus() +{ + Rect rect,boundary; + Matrix mat; + + if (mouse_active || !cur_focus) return; + + /* rect is the bbox in screen coordinates */ + + // Compute the bounding box in screen coordinates + cur_focus->character->getBoundingBox(&boundary,cur_focus); + mat = (*gd->adjust) * cur_focus->renderMatrix; + transformBoundingBox(&rect, &mat, &boundary, 1); + + gd->drawBox(rect.xmin, rect.ymin, rect.xmax, rect.ymax); +} + +void +FlashMovie::renderMovie() +{ + CInputScript *script,*prev,*next; + Rect clipping; + Matrix identity; + + clipping.reset(); + + // First pass to update the clipping region + for (script = this->main; script != NULL; script = script->next) { + if (script->level == -1) { + clipping.xmin = -32768; + clipping.ymin = -32768; + clipping.xmax = 32767; + clipping.ymax = 32767; + continue; + } + if (script->program == NULL) continue; + if (script->program->dl->bbox.xmin == LONG_MAX) continue; + transformBoundingBox(&clipping, &identity, &script->program->dl->bbox, 0); + script->program->render = 0; + } + + if (clipping.xmin == LONG_MAX) return; + + // Update the clipping region + gd->updateClippingRegion(&clipping); + gd->clearCanvas(); + + // Second pass to render the movie + for (script = this->main; script != NULL; script = script->next) { + if (script->level == -1) continue; + if (script->program == NULL) continue; + script->program->dl->render(gd); + } + renderFocus(); + + // Final pass to delete some movies + script = this->main; + prev = 0; + while (script != NULL) { + if (script->level == -1) { + next = script->next; + if (prev == 0) { + this->main = next; + } else { + prev->next = next; + } + delete script; + script = next; + } else { + prev = script; + script = script->next; + } + } +} diff --git a/core/multimedia/opieplayer/libflash/movie.h b/core/multimedia/opieplayer/libflash/movie.h new file mode 100644 index 0000000..d83ce79 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/movie.h @@ -0,0 +1,68 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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 _MOVIE_H_ +#define _MOVIE_H_ + +#include "swf.h" + +struct FlashMovie { + /* true if a button has been moved */ + int buttons_updated; + + /* current keyboard focus */ + DisplayListEntry *cur_focus; + + /* mouse state */ + long mouse_active; + long mouse_x; + long mouse_y; + int button_pressed; + + Button *lost_over; + + /* a button can return to a given state after some time */ + FlashEvent scheduledEvent; + struct timeval scheduledTime; + + int refresh; + + CInputScript *main; + long msPerFrame; + GraphicDevice *gd; + SoundMixer *sm; + + void (*getUrl)(char *,char *, void *); + void *getUrlClientData; + + void (*getSwf)(char *url, int level, void *clientData); + void *getSwfClientData; + + void (*cursorOnOff)(int , void *); + void *cursorOnOffClientData; + + FlashMovie(); + ~FlashMovie(); + int processMovie(GraphicDevice *gd, SoundMixer *sm); + int handleEvent(GraphicDevice *gd, SoundMixer *sm, FlashEvent *event); + void renderMovie(); + void renderFocus(); +}; + +#endif /* _MOVIE_H_ */ diff --git a/core/multimedia/opieplayer/libflash/program.cc b/core/multimedia/opieplayer/libflash/program.cc new file mode 100644 index 0000000..c6e8c0f --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/program.cc @@ -0,0 +1,921 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#define NOTHING 0x0 +#define WAKEUP 0x1 +#define GOTO 0x2 +#define REFRESH 0x4 + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +#define PRINT 0 + +int debug = 0; + +Program::Program(FlashMovie *movie, long n) +{ + long f; + + this->movie = movie; + + totalFrames = 0; + + dl = new DisplayList(movie); + if (dl == NULL) return; + frames = new Frame[n]; + if (frames == NULL) { + delete dl; + return; + } + + nbFrames = 0; + totalFrames = n; + currentFrame = 0; + loadingFrame = 0; + movieWait = 1; + nextFrame = currentFrame; + for(f = 0; f < n; f++) + { + frames[f].controls = 0; + frames[f].label = NULL; + } + + movieStatus = MoviePlay; + settings = 0; +} + +Program::~Program() +{ + int i; + Control *ctrl, *ctrl1; + + delete dl; + + if (frames != NULL) { + for(i=0;inext; + ctrl->next = NULL; + delete ctrl; + ctrl = ctrl1; + } + } + + delete[] frames; + } +} + +void +Program::validateLoadingFrame() +{ + nbFrames = loadingFrame; + loadingFrame++; + movieWait = 0; +} + +Frame * +Program::getFrames() +{ + return frames; +} + +long +Program::getNbFrames() +{ + return nbFrames; +} + +DisplayList * +Program::getDisplayList() +{ + return dl; +} + +long +Program::getCurrentFrame() +{ + return currentFrame; +} + +void +Program::setCurrentFrame(long n) +{ + currentFrame = n; + nextFrame = n; + //refresh = 1; +} + +void +Program::gotoFrame(GraphicDevice *gd, long frame) +{ + long f; + + //printf("GotoFrame %d (Current = %d)\n", frame, currentFrame); + dl->clearList(); + + for(f=0; f <= frame; f++) { + runFrame(gd, 0, f, 0); + } +} + +long +Program::runFrame(GraphicDevice *gd, SoundMixer *sm, long f, long action) +{ + Control *ctrl; + Character *character; + Matrix *matrix; + Cxform *cxform; + long status = NOTHING; + long update = 0; + char *name; + +#if PRINT&1 + if (action) printf("Prog %x (dl=%x): Frame N° %d/%d\n", this, this->dl, f, nbFrames-1); +#endif + movie->buttons_updated = 0; + + for(ctrl = frames[f].controls; ctrl; ctrl = ctrl->next) + { + switch (ctrl->type) + { + case ctrlPlaceObject: + case ctrlPlaceObject2: + character = 0; + matrix = 0; + cxform = 0; + name = ""; + if (ctrl->flags & placeHasCharacter) { + character = ctrl->character; + } + if (ctrl->flags & placeHasMatrix) { + matrix = &ctrl->matrix; + } + if (ctrl->flags & placeHasColorXform) { + cxform = &ctrl->cxform; + } + if (ctrl->flags & placeHasName) { + name = ctrl->name; + } + if (!ctrl->clipDepth) { // Ignore + dl->placeObject(gd,character, ctrl->depth, matrix, cxform, name); + update = 1; + } + break; + case ctrlRemoveObject: + character = ctrl->character; + + if (!character) break; // Should not happen + + dl->removeObject(gd, character, ctrl->depth); + if (action) { + character->reset(); + update = 1; + } + break; + case ctrlRemoveObject2: + character = dl->removeObject(gd,NULL, ctrl->depth); + if (character && action) { + character->reset(); + update = 1; + } + break; + // Actions + case ctrlDoAction: + if (action) { + status = doAction(gd, ctrl->actionRecords, sm); + } + break; + case ctrlStartSound: + if (action && sm) { + sm->startSound( (Sound *)ctrl->character ); + } + break; + case ctrlStopSound: + if (action && sm) { + sm->stopSounds(); + } + break; + case ctrlBackgroundColor: + if (action) { + if (gd->setBackgroundColor(ctrl->color)) { + dl->bbox.xmin = -32768; + dl->bbox.ymin = -32768; + dl->bbox.xmax = 32768; + dl->bbox.ymax = 32768; + } + } + break; + } + } + if (movie->buttons_updated) { + dl->updateButtons(movie); + } + + if (status & GOTO) { + if (nextFrame < nbFrames) { + gotoFrame(gd,nextFrame); + if (nextFrame != f) + if (movieStatus == MoviePaused) runFrame(gd,sm,nextFrame); + update = 1; + } + } + +#if PRINT&1 + if (action) printf("Frame N° %d ready\n", f); +#endif + return update; +} + +long +Program::nestedMovie(GraphicDevice *gd, SoundMixer *sm, Matrix *mat, Cxform *cxform) +{ + if (movieStatus == MoviePlay) { + // Movie Beeing Played + advanceFrame(); + if (currentFrame == 0) { + dl->clearList(); + } + runFrame(gd, sm, currentFrame); + if (nbFrames == 1) { + pauseMovie(); + } + } + + return (movieStatus == MoviePlay); +} + +long +Program::processMovie(GraphicDevice *gd, SoundMixer *sm) +{ + int wakeUp = 0; + +#if PRINT&1 + printf("Prog %x (dl=%x): Current = %d Next = %d Wait = %d Status = %d\n", this, this->dl, currentFrame, nextFrame, movieWait, movieStatus); +#endif + + if (movieStatus == MoviePlay && movieWait == 0) { + // Movie Beeing Played + advanceFrame(); + if (currentFrame == 0) { + dl->clearList(); + } + wakeUp |= runFrame(gd, sm, currentFrame); + wakeUp |= dl->updateSprites(); + if (nextFrame == nbFrames) { + if (nbFrames != totalFrames) { + movieWait = 1; + } else if ((settings & PLAYER_LOOP) == 0) { + pauseMovie(); + } + } + } else { + wakeUp |= dl->updateSprites(); + } + + if (wakeUp) { + render = 1; + } + + return (wakeUp || movieStatus == MoviePlay); +} + +/* timer (ms) -1 = delete timer */ +void setFlashTimer(struct timeval *tv, int time_ms) +{ + if (time_ms == -1) { + tv->tv_sec = -1; + } else { + gettimeofday(tv,0); + + tv->tv_usec += time_ms*1000; + while (tv->tv_usec > 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } + } +} + +int checkFlashTimer(struct timeval *tv) +{ + struct timeval now; + + if (tv->tv_sec == -1) return 0; + + gettimeofday(&now,0); + return (now.tv_sec > tv->tv_sec || + (now.tv_sec == tv->tv_sec && now.tv_usec >= tv->tv_usec)); +} + +/* bbox */ +typedef struct { + long x1,y1,x2,y2; +} ButtonBoundingBox; + + +static void button_bbox_func(void *id, long y, long start, long end) +{ + ButtonBoundingBox *h = (ButtonBoundingBox *) id; + + if (y < h->y1) h->y1 = y; + if (y > h->y2) h->y2 = y; + if (start < h->x1) h->x1 = start; + if (end > h->x2) h->x2 = end; +} + +void computeBBox(FlashMovie *movie, Rect *rect, DisplayListEntry *e) +{ + ButtonBoundingBox bb; + + bb.x1 = LONG_MAX; + bb.y1 = LONG_MAX; + bb.x2 = LONG_MIN; + bb.y2 = LONG_MIN; + + e->character->getRegion(movie->gd,&e->renderMatrix,&bb,button_bbox_func); + + rect->xmin = bb.x1 / FRAC; + rect->xmax = bb.x2 / FRAC; + rect->ymin = bb.y1; + rect->ymax = bb.y2; +} + +void transform_coords(long *x_ptr,long *y_ptr, long cx, long cy, long dx, long dy) +{ + long x,y,x1,y1; + x = *x_ptr; + y = *y_ptr; + + x -= cx; + y -= cy; + + if (dx < 0) { + /* left */ + x1 = - x; + y1 = y; + } else if (dy < 0) { + /* up */ + y1 = x; + x1 = -y; + } else if (dy > 0) { + /* down */ + y1 = x; + x1 = y; + } else { + /* right */ + x1 = x; + y1 = y; + } + + *x_ptr = x1; + *y_ptr = y1; +} + +typedef struct { + FlashMovie *movie; + DisplayListEntry *emin,*cur_focus; + long dmin; + long w,cx,cy,dx,dy; +} ButtonFocus; + +static int button_focus(void *opaque, Program *prg, DisplayListEntry *e) +{ + ButtonFocus *h=(ButtonFocus *)opaque; + Rect rect; + long d,x,y; + + if (e != h->cur_focus) { + computeBBox(h->movie,&rect,e); + x = (rect.xmin + rect.xmax) / 2; + y = (rect.ymin + rect.ymax) / 2; + + /* transform the coords so that the angular sector is directed to the right */ + transform_coords(&x,&y,h->cx,h->cy,h->dx,h->dy); + + /* inside it ? */ + if ( x >= 0 && + (y - x - h->w) <= 0 && + (y + x + h->w) >= 0) { + d = x*x + y*y; + + if (d < h->dmin) { + h->dmin = d; + h->emin = e; + } + } + } + return 0; +} + +DisplayListEntry *moveFocus(FlashMovie *movie, long dx, long dy, + DisplayListEntry *cur_focus) +{ + Rect cur_rect; + ButtonFocus h; + + h.movie = movie; + h.dx = dx; + h.dy = dy; + + computeBBox(movie,&cur_rect,cur_focus); + /* center */ + h.cx = (cur_rect.xmin + cur_rect.xmax) / 2; + h.cy = (cur_rect.ymin + cur_rect.ymax) / 2; + + /* width/2 of the 45 degrees angular sector */ + if (dy != 0) { + /* for vertical displacement, we have a larger width */ + h.w = (cur_rect.xmax - cur_rect.xmin) / 2; + } else { + /* zero width for horizontal displacement */ + h.w = 0; + } + + /* now we select the nearest button in the angular sector */ + h.dmin = LONG_MAX; + h.emin = NULL; + h.cur_focus = cur_focus; + + exploreButtons(movie, &h, button_focus); + + return h.emin; +} + +static int button_newfocus(void *opaque, Program *prg, DisplayListEntry *e) +{ + * (DisplayListEntry **)opaque = e; + return 2; +} + +static int button_nextfocus(void *opaque, Program *prg, DisplayListEntry *e) +{ + static int found = 0; + DisplayListEntry **focus; + + focus = (DisplayListEntry **)opaque; + if (found) { + *focus = e; + found = 0; + return 2; + } + if (e == *focus) { + found = 1; + } + return 0; +} + + +/* XXX: should not be here (one level upper) */ +long +Program::handleEvent(GraphicDevice *gd, SoundMixer *sm, FlashEvent *fe) +{ + ActionRecord *action; + Program *prog; + long status = 0; + DisplayListEntry *cur_focus, *new_focus; + long dx,dy; + int refresh; + + refresh = 0; + + switch(fe->type) { + + case FeKeyRelease: + if (movie->mouse_active == 0) { + + if (movie->cur_focus) { + movie->cur_focus->owner->updateBoundingBox(movie->cur_focus); + movie->cur_focus->renderState = stateOver; + movie->cur_focus->owner->updateBoundingBox(movie->cur_focus); + } + } + break; + + case FeKeyPress: + + movie->mouse_active = 0; + + /* find the button which has the focus */ + cur_focus = movie->cur_focus; + + if (fe->key == FeKeyEnter) { + /* selection */ + if (cur_focus) { + /* select the button */ + cur_focus->owner->updateBoundingBox(cur_focus); + cur_focus->renderState = stateDown; + ((Button *)cur_focus->character)->updateButtonState(cur_focus); + cur_focus->owner->updateBoundingBox(cur_focus); + + movie->scheduledEvent.type = FeKeyRelease; + movie->scheduledEvent.key = FeKeyEnter; + + setFlashTimer(&movie->scheduledTime, 250); /* 250 ms down */ + } + } else { + /* displacement */ + + if (cur_focus == NULL) { + /* no current focus : set one */ + exploreButtons(movie, &cur_focus, button_newfocus); + if (cur_focus) { + cur_focus->renderState = stateOver; + ((Button *)cur_focus->character)->updateButtonState(cur_focus); + cur_focus->owner->updateBoundingBox(cur_focus); + } + movie->cur_focus = cur_focus; + } else { + /* move the focus (test) */ + switch(fe->key) { + case FeKeyNext: + /* Next available */ + cur_focus->owner->updateBoundingBox(cur_focus); + cur_focus->renderState = stateUp; + ((Button *)cur_focus->character)->updateButtonState(cur_focus); + cur_focus->owner->updateBoundingBox(cur_focus); + exploreButtons(movie, &cur_focus, button_nextfocus); + if (cur_focus) { + cur_focus->renderState = stateOver; + ((Button *)cur_focus->character)->updateButtonState(cur_focus); + cur_focus->owner->updateBoundingBox(cur_focus); + } + movie->cur_focus = cur_focus; + dx = 0; + dy = 0; + break; + case FeKeyUp: + dx = 0; + dy = -1; + break; + case FeKeyDown: + dx = 0; + dy = 1; + break; + case FeKeyLeft: + dx = -1; + dy = 0; + break; + case FeKeyRight: + dx = 1; + dy = 0; + break; + default: + /* should not happen */ + dx = 0; + dy = 0; + break; + } + + if (dx != 0 || dy != 0) { + + new_focus = moveFocus(movie, dx, dy, cur_focus); + if (new_focus) { + cur_focus->owner->updateBoundingBox(cur_focus); + cur_focus->renderState = stateUp; + ((Button *)cur_focus->character)->updateButtonState(cur_focus); + cur_focus->owner->updateBoundingBox(cur_focus); + + if (computeActions(movie, &prog, &action)) { + status |= prog->doAction(gd, action, sm); + } + + new_focus->renderState = stateOver; + ((Button *)new_focus->character)->updateButtonState(new_focus); + movie->cur_focus = new_focus; + new_focus->owner->updateBoundingBox(new_focus); + } else { + return 0; + } + } + } + if (movie->cur_focus == NULL) return 0; + } + break; + + case FeMouseMove: + movie->mouse_active = 1; + movie->mouse_x = fe->x * FRAC; + movie->mouse_y = fe->y * FRAC; + dl->updateButtons(movie); + break; + + case FeButtonPress: + movie->mouse_active = 1; + movie->button_pressed = 1; + dl->updateButtons(movie); + break; + + case FeButtonRelease: + movie->mouse_active = 1; + movie->button_pressed = 0; + dl->updateButtons(movie); + break; + + default: + return 0; + } + + if (computeActions(movie, &prog, &action)) { + status |= prog->doAction(gd, action, sm); + } + + if (status & REFRESH) { + status |= WAKEUP; + refresh = 1; + } + if (status & GOTO) { + if (nextFrame < nbFrames) { + gotoFrame(gd, nextFrame); + if (movieStatus == MoviePaused) runFrame(gd,sm,nextFrame); + refresh = 1; + } + } + + if (refresh) { + dl->updateSprites(); + render = 1; + } + return (refresh || movieStatus == MoviePlay); +} + +long +Program::doAction(GraphicDevice *gd, ActionRecord *action, SoundMixer *sm) +{ + long status = NOTHING; + long f; + char *target = ""; + long skip = 0; + + while(action) + { + if (skip) skip--; + else + switch (action->action) + { + case ActionPlaySound: +#if PRINT&2 + printf("Prog %x : PlaySound\n", this); +#endif + if (sm) { + sm->startSound(action->sound); + } + status |= WAKEUP; + break; + case ActionRefresh: +#if PRINT&2 + printf("Prog %x : Refresh\n", this); +#endif + status |= REFRESH; + break; + case ActionGotoFrame: +#if PRINT&2 + printf("Prog %x : GotoFrame %d\n", this, action->frameIndex); +#endif + if (target[0] == 0) { + if (action->frameIndex < nbFrames) { + currentFrame = action->frameIndex; + pauseMovie(); + status |= WAKEUP|GOTO; + } + } + break; + case ActionGetURL: +#if PRINT&2 + printf("Prog %x : GetURL %s target = %s\n", this, action->url, action->target); +#endif + { + int len,level; + len = strlen(action->target); + + if (len > 6 && memcmp(action->target,"_level", 6) == 0) { + level = atoi(action->target + 6); + loadNewSwf(movie, action->url, level); + } else { + if (movie->getUrl) { + movie->getUrl(action->url, action->target, movie->getUrlClientData); + } + } + } + break; + case ActionNextFrame: + nextFrame = currentFrame+1; + movieStatus = MoviePlay; + status |= WAKEUP; + break; + case ActionPrevFrame: + nextFrame = currentFrame-1; + status |= WAKEUP|GOTO; + break; + case ActionPlay: +#if PRINT&2 + printf("Prog %x : Play\n", this); +#endif + if (target[0] == 0) { + movieStatus = MoviePlay; + if ((status & GOTO) == 0) { + if (currentFrame == nextFrame) advanceFrame(); + } + status |= WAKEUP; + } + break; + case ActionStop: +#if PRINT&2 + printf("Prog %x : Stop\n", this); +#endif + if (target[0] == 0) { + movieStatus = MoviePaused; + nextFrame = currentFrame; + } + break; + case ActionToggleQuality: + break; + case ActionStopSounds: + if (sm) { + sm->stopSounds(); + } + break; + case ActionWaitForFrame: + if (action->frameIndex >= nbFrames) { + skip = action->skipCount; + } + break; + case ActionSetTarget: +#if PRINT&2 + printf("Prog %x : SetTarget '%s'\n", this, action->target); +#endif + target = action->target; + break; + case ActionGoToLabel: +#if PRINT&2 + printf("Prog %x : GotoFrame '%s'\n", this, action->frameLabel); +#endif + f = searchFrame(gd, action->frameLabel, target); + if (f >= 0) { + currentFrame = f; + pauseMovie(); + status |= WAKEUP|GOTO; + } else { + status |= REFRESH; + } + break; + } + action = action->next; + } + return status; +} + +void +Program::setCurrentFrameLabel(char *label) +{ + frames[loadingFrame].label = label; +} + +void +Program::rewindMovie() +{ + currentFrame = 0; + nextFrame = 0; +} + +void +Program::pauseMovie() +{ + movieStatus = MoviePaused; + nextFrame = currentFrame; +} + +void +Program::continueMovie() +{ + movieStatus = MoviePlay; +} + +void +Program::nextStepMovie() +{ + if (movieStatus == MoviePaused) { + advanceFrame(); + } +} + +void +Program::advanceFrame() +{ + currentFrame = nextFrame; + nextFrame = currentFrame+1; + if (currentFrame == nbFrames) { + currentFrame = 0; + nextFrame = 0; + movieStatus = MoviePlay; + } +} + +void +Program::addControlInCurrentFrame(Control *ctrl) +{ + Control *c; + + ctrl->next = 0; + if (frames[loadingFrame].controls == 0) { + frames[loadingFrame].controls = ctrl; + } else { + for(c = frames[loadingFrame].controls; c->next; c = c->next); + c->next = ctrl; + } +} + +void +Program::modifySettings(long flags) +{ + settings = flags; +} + +long +Program::searchFrame(GraphicDevice *gd, char *label, char *target) +{ + long f; + DisplayListEntry *e; + Program *prg; + + // Current movie + if (target[0] == 0) { + for(f=0; f < nbFrames; f++) + { + if (frames[f].label && !strcmp(label,frames[f].label)) { + return f; + } + } + } + + // Kludge !!! + for (e = dl->list; e; e = e->next) { + if (e->character->isSprite()) { + prg = ((Sprite *)e->character)->program; + f = prg->searchFrame(gd,label,""); + if (f >= 0 && f < prg->nbFrames) { + prg->dl->updateBoundingBox(e); + prg->gotoFrame(gd, f); + prg->nextFrame = f; + prg->dl->updateBoundingBox(e); + return -1; + } + } + } + + return -1; +} + +void loadNewSwf(FlashMovie *movie, char *url, int level) +{ + CInputScript *s,*prev,**l; + + if (movie->getSwf == NULL) return; + + for(s = movie->main, prev = 0; s != NULL; prev = s, s = s->next) { + if (s->level == level) { + // Mark movie to be deleted + s->level = -1; + break; + } + } + + //printf("Unload movie @ %d\n", level); + + if (*url == 0) return; // Just UnloadMovie + + s = new CInputScript(level); + if (s == NULL) return; + + /* insert it in the right order */ + l = &movie->main; + while (*l != NULL && (*l)->level < level) l = &(*l)->next; + s->next = *l; + *l = s; + + // Notify the external loader of a new movie to load + movie->getSwf(url, level, movie->getSwfClientData); +} diff --git a/core/multimedia/opieplayer/libflash/program.h b/core/multimedia/opieplayer/libflash/program.h new file mode 100644 index 0000000..7672d88 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/program.h @@ -0,0 +1,185 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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 _PROGRAM_H_ +#define _PROGRAM_H_ + +enum ControlType { + ctrlPlaceObject, + ctrlPlaceObject2, + ctrlRemoveObject, + ctrlRemoveObject2, + ctrlDoAction, + ctrlStartSound, + ctrlStopSound, + ctrlBackgroundColor +}; + +enum PlaceFlags { + placeIsMove = 0x01, + placeHasCharacter = 0x02, + placeHasMatrix = 0x04, + placeHasColorXform = 0x08, + placeHasRatio = 0x10, + placeHasName = 0x20, + placeHasClip = 0x40 +}; + +struct Control { + ControlType type; + + // Place, Remove, Sound + Character *character; + long depth; + + // Place 1&2 + PlaceFlags flags; + Matrix matrix; + Cxform cxform; + long ratio; + long clipDepth; + char *name; + + // BackgroundColor + Color color; + + // DoAction + ActionRecord *actionRecords; + + struct Control *next; + + + // Methods + + void addActionRecord( ActionRecord *ar) + { + ar->next = 0; + + if (actionRecords == 0) { + actionRecords = ar; + } else { + ActionRecord *current; + + for(current = actionRecords; current->next; current = current->next); + + current->next = ar; + } + }; + + Control() + { + actionRecords = 0; + cxform.aa = 1.0; cxform.ab = 0; + cxform.ra = 1.0; cxform.rb = 0; + cxform.ga = 1.0; cxform.gb = 0; + cxform.ba = 1.0; cxform.bb = 0; + ratio = 0; + clipDepth = 0; + name = 0; + }; + + ~Control() + { + ActionRecord *ar,*del; + for(ar = actionRecords; ar;) + { + del = ar; + ar = ar->next; + delete del; + } + if (name) { + free(name); + } + }; +}; + +struct Frame { + char *label; + Control *controls; // Controls for this frame +}; + +enum MovieStatus { + MoviePaused, + MoviePlay +}; + +struct FlashMovie; + +struct Program { + DisplayList *dl; + + Frame *frames; // Array + long nbFrames; // Number of valid frames + long currentFrame; + long loadingFrame; + long totalFrames; // Total expected number of frames + long nextFrame; + int movieWait; // If true freeze movie until next loaded frame + MovieStatus movieStatus; + Sound *currentSound; + long settings; + FlashMovie *movie; + long render; // True if needed to be rendered + + Program(FlashMovie *movie,long n); + ~Program(); + + void rewindMovie(); + void pauseMovie(); + void continueMovie(); + void nextStepMovie(); + void gotoFrame(GraphicDevice *gd, long f); + + long processMovie(GraphicDevice *, SoundMixer *); + long nestedMovie(GraphicDevice *, SoundMixer *, Matrix *, Cxform *); + long runFrame(GraphicDevice *, SoundMixer *, long f, long action=1); + long handleEvent(GraphicDevice *, SoundMixer *, FlashEvent *); + long doAction(GraphicDevice *gd, ActionRecord *action, SoundMixer *); + void setCurrentFrameLabel(char *label); + void advanceFrame(); + void addControlInCurrentFrame(Control *ctrl); + void setGetUrlMethod( void (*)(char *, char *, void *), void *); + void modifySettings(long flags); + long searchFrame(GraphicDevice *gd, char *, char *); + void validateLoadingFrame(); + long getCurrentFrame(); + void setCurrentFrame(long); + + Frame *getFrames(); + long getNbFrames(); + + DisplayList *getDisplayList(); + +#ifdef DUMP + void dump(BitStream *bs); +static void dumpActions(BitStream *bs, ActionRecord *actions); +#endif +}; + +DisplayListEntry *findFocus(DisplayList *dl); +void setFlashTimer(struct timeval *tv, int time_ms); +int checkFlashTimer(struct timeval *tv); + +void loadNewSwf(FlashMovie *movie, char *url, int level); + +void computeBBox(FlashMovie *movie, Rect *rect, DisplayListEntry *e); + +long processMovie(FlashMovie *movie); + +#endif /* _PROGRAM_H_ */ diff --git a/core/multimedia/opieplayer/libflash/rect.h b/core/multimedia/opieplayer/libflash/rect.h new file mode 100644 index 0000000..cb84eb3 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/rect.h @@ -0,0 +1,55 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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 _RECT_H_ +#define _RECT_H_ + +struct Rect +{ + long xmin; + long xmax; + long ymin; + long ymax; + + long getWidth() { + return xmax-xmin; + }; + + long getHeight() { + return ymax-ymin; + }; + + void print() { + printf("Xmin = %d Xmax = %d Ymin = %d Ymax = %d\n", + (int)xmin,(int)xmax,(int)ymin,(int)ymax); + }; + + void reset() { + xmin = LONG_MAX; + ymin = LONG_MAX; + xmax = LONG_MIN; + ymax = LONG_MIN; + }; + +#ifdef DUMP + void dump(BitStream *bs); +#endif +}; + +#endif /* _RECT_H_ */ diff --git a/core/multimedia/opieplayer/libflash/script.cc b/core/multimedia/opieplayer/libflash/script.cc new file mode 100644 index 0000000..db65819 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/script.cc @@ -0,0 +1,1988 @@ +#include "swf.h" + +//////////////////////////////////////////////////////////// +// This file is derived from the 'buggy' SWF parser provided +// by Macromedia. +// +// Modifications : Olivier Debon +// + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +#define printf(fmt,args...) + +////////////////////////////////////////////////////////////////////// +// Inline input script object methods. +////////////////////////////////////////////////////////////////////// + +// +// Inlines to parse a Flash file. +// +inline U8 CInputScript::GetByte(void) +{ + return m_fileBuf[m_filePos++]; +} + +inline U16 CInputScript::GetWord(void) +{ + U8 * s = m_fileBuf + m_filePos; + m_filePos += 2; + return (U16) s[0] | ((U16) s[1] << 8); +} + +inline U32 CInputScript::GetDWord(void) +{ + U8 * s = m_fileBuf + m_filePos; + m_filePos += 4; + return (U32) s[0] | ((U32) s[1] << 8) | ((U32) s[2] << 16) | ((U32) s [3] << 24); +} + + + + +////////////////////////////////////////////////////////////////////// +// Input script object methods. +////////////////////////////////////////////////////////////////////// + +CInputScript::CInputScript(int level) +// Class constructor. +{ + this->level = level; + + // Initialize the input pointer. + m_fileBuf = NULL; + + // Initialize the file information. + m_filePos = 0; + m_fileSize = 0; + m_fileVersion = 0; + + // Initialize the bit position and buffer. + m_bitPos = 0; + m_bitBuf = 0; + + // Initialize the output file. + m_outputFile = NULL; + + // Set to true if we wish to dump all contents long form + m_dumpAll = false; + + // if set to true will dump image guts (i.e. jpeg, zlib, etc. data) + m_dumpGuts = false; + + needHeader = 1; + program = 0; + + outOfMemory = 0; + + next = NULL; + + return; +} + + +CInputScript::~CInputScript(void) +// Class destructor. +{ + // Free the buffer if it is there. + if (m_fileBuf) + { + delete program; + m_fileBuf = NULL; + m_fileSize = 0; + } +} + + +U16 CInputScript::GetTag(void) +{ + // Save the start of the tag. + m_tagStart = m_filePos; + + if (m_actualSize-m_filePos < 2) return notEnoughData; + + // Get the combined code and length of the tag. + U16 code = GetWord(); + + // The length is encoded in the tag. + U32 len = code & 0x3f; + + // Remove the length from the code. + code = code >> 6; + + // Determine if another long word must be read to get the length. + if (len == 0x3f) { + if (m_actualSize-m_filePos < 4) return notEnoughData; + len = (U32) GetDWord(); + } + + // Determine the end position of the tag. + m_tagEnd = m_filePos + (U32) len; + m_tagLen = (U32) len; + + return code; +} + + +void CInputScript::GetRect (Rect * r) +{ + InitBits(); + int nBits = (int) GetBits(5); + r->xmin = GetSBits(nBits); + r->xmax = GetSBits(nBits); + r->ymin = GetSBits(nBits); + r->ymax = GetSBits(nBits); +} + +void CInputScript::GetMatrix(Matrix* mat) +{ + InitBits(); + + // Scale terms + if (GetBits(1)) + { + int nBits = (int) GetBits(5); + mat->a = (float)(GetSBits(nBits))/(float)0x10000; + mat->d = (float)(GetSBits(nBits))/(float)0x10000; + } + else + { + mat->a = mat->d = 1.0; + } + + // Rotate/skew terms + if (GetBits(1)) + { + int nBits = (int)GetBits(5); + mat->c = (float)(GetSBits(nBits))/(float)0x10000; + mat->b = (float)(GetSBits(nBits))/(float)0x10000; + } + else + { + mat->b = mat->c = 0.0; + } + + // Translate terms + int nBits = (int) GetBits(5); + mat->tx = GetSBits(nBits); + mat->ty = GetSBits(nBits); +} + + +void CInputScript::GetCxform(Cxform* cx, BOOL hasAlpha) +{ + int flags; + int nBits; + float aa; long ab; + float ra; long rb; + float ga; long gb; + float ba; long bb; + + InitBits(); + + flags = (int) GetBits(2); + nBits = (int) GetBits(4); + aa = 1.0; ab = 0; + if (flags & 1) + { + ra = (float) GetSBits(nBits)/256.0; + ga = (float) GetSBits(nBits)/256.0; + ba = (float) GetSBits(nBits)/256.0; + if (hasAlpha) aa = (float) GetSBits(nBits)/256.0; + } + else + { + ra = ga = ba = 1.0; + } + if (flags & 2) + { + rb = (S32) GetSBits(nBits); + gb = (S32) GetSBits(nBits); + bb = (S32) GetSBits(nBits); + if (hasAlpha) ab = (S32) GetSBits(nBits); + } + else + { + rb = gb = bb = 0; + } + if (cx) { + cx->aa = aa; + cx->ab = ab; + cx->ra = ra; + cx->rb = rb; + cx->ga = ga; + cx->gb = gb; + cx->ba = ba; + cx->bb = bb; + } +} + + +/* XXX: should allocate string */ +char *CInputScript::GetString(void) +{ + // Point to the string. + char *str = (char *) &m_fileBuf[m_filePos]; + + // Skip over the string. + while (GetByte()); + + return str; +} + +void CInputScript::InitBits(void) +{ + // Reset the bit position and buffer. + m_bitPos = 0; + m_bitBuf = 0; +} + + +S32 CInputScript::GetSBits (S32 n) +// Get n bits from the string with sign extension. +{ + // Get the number as an unsigned value. + S32 v = (S32) GetBits(n); + + // Is the number negative? + if (v & (1L << (n - 1))) + { + // Yes. Extend the sign. + v |= -1L << n; + } + + return v; +} + + +U32 CInputScript::GetBits (S32 n) +// Get n bits from the stream. +{ + U32 v = 0; + + for (;;) + { + S32 s = n - m_bitPos; + if (s > 0) + { + // Consume the entire buffer + v |= m_bitBuf << s; + n -= m_bitPos; + + // Get the next buffer + m_bitBuf = GetByte(); + m_bitPos = 8; + } + else + { + // Consume a portion of the buffer + v |= m_bitBuf >> -s; + m_bitPos -= n; + m_bitBuf &= 0xff >> (8 - m_bitPos); // mask off the consumed bits + return v; + } + } +} + +void CInputScript::ParseFreeCharacter() +{ + U32 tagid = (U32) GetWord(); + + tagid = tagid; + + printf("tagFreeCharacter \ttagid %-5u\n", tagid); +} + + +void CInputScript::ParsePlaceObject() +{ + Control *ctrl; + + ctrl = new Control; + if (ctrl == NULL) { + outOfMemory = 1; + return; + } + ctrl->type = ctrlPlaceObject; + ctrl->flags = (PlaceFlags)(placeHasMatrix | placeHasCharacter); + + ctrl->character = getCharacter(GetWord()); + ctrl->depth = GetWord(); + + GetMatrix(&(ctrl->matrix)); + + if ( m_filePos < m_tagEnd ) + { + ctrl->flags = (PlaceFlags)(ctrl->flags | placeHasColorXform); + + GetCxform(&ctrl->cxform, false); + } + + program->addControlInCurrentFrame(ctrl); +} + + +void CInputScript::ParsePlaceObject2() +{ + Control *ctrl; + + ctrl = new Control; + if (ctrl == NULL) { + outOfMemory = 1; + return; + } + ctrl->type = ctrlPlaceObject2; + + ctrl->flags = (PlaceFlags)GetByte(); + ctrl->depth = GetWord(); + + // Get the tag if specified. + if (ctrl->flags & placeHasCharacter) + { + ctrl->character = getCharacter(GetWord()); + } + + // Get the matrix if specified. + if (ctrl->flags & placeHasMatrix) + { + GetMatrix(&(ctrl->matrix)); + } + + // Get the color transform if specified. + if (ctrl->flags & placeHasColorXform) + { + GetCxform(&ctrl->cxform, true); + } + + // Get the ratio if specified. + if (ctrl->flags & placeHasRatio) + { + ctrl->ratio = GetWord(); + } + + // Get the ratio if specified. + if (ctrl->flags & placeHasName) + { + ctrl->name = strdup(GetString()); + } + + // Get the clipdepth if specified. + if (ctrl->flags & placeHasClip) + { + ctrl->clipDepth = GetWord(); + } + + program->addControlInCurrentFrame(ctrl); +} + + +void CInputScript::ParseRemoveObject() +{ + Control *ctrl; + + ctrl = new Control; + if (ctrl == NULL) { + outOfMemory = 1; + return; + } + ctrl->type = ctrlRemoveObject; + ctrl->character = getCharacter(GetWord()); + ctrl->depth = GetWord(); + + program->addControlInCurrentFrame(ctrl); +} + + +void CInputScript::ParseRemoveObject2() +{ + Control *ctrl; + + ctrl = new Control; + if (ctrl == NULL) { + outOfMemory = 1; + return; + } + ctrl->type = ctrlRemoveObject2; + ctrl->depth = GetWord(); + + program->addControlInCurrentFrame(ctrl); +} + + +void CInputScript::ParseSetBackgroundColor() +{ + Control *ctrl; + + ctrl = new Control; + if (ctrl == NULL) { + outOfMemory = 1; + return; + } + ctrl->type = ctrlBackgroundColor; + ctrl->color.red = GetByte(); + ctrl->color.green = GetByte(); + ctrl->color.blue = GetByte(); + + program->addControlInCurrentFrame(ctrl); +} + + +void CInputScript::ParseDoAction() +{ + Control *ctrl; + ActionRecord *ar; + + ctrl = new Control; + if (ctrl == NULL) { + outOfMemory = 1; + return; + } + ctrl->type = ctrlDoAction; + + do { + ar = ParseActionRecord(); + if (ar) { + ctrl->addActionRecord( ar ); + } + if (outOfMemory) { + return; + } + } while (ar); + + program->addControlInCurrentFrame(ctrl); + +} + + +void CInputScript::ParseStartSound() +{ + Control *ctrl; + + ctrl = new Control; + if (ctrl == NULL) { + outOfMemory = 1; + return; + } + ctrl->character = getCharacter(GetWord()); + ctrl->type = ctrlStartSound; + + program->addControlInCurrentFrame(ctrl); + + if (!m_dumpAll) + return; + + U32 code = GetByte(); + + printf("code %-3u", code); + + if ( code & soundHasInPoint ) + printf(" inpoint %u ", GetDWord()); + if ( code & soundHasOutPoint ) + printf(" oupoint %u", GetDWord()); + if ( code & soundHasLoops ) + printf(" loops %u", GetWord()); + + printf("\n"); + if ( code & soundHasEnvelope ) + { + int points = GetByte(); + + for ( int i = 0; i < points; i++ ) + { + printf("\n"); + printf("mark44 %u", GetDWord()); + printf(" left chanel %u", GetWord()); + printf(" right chanel %u", GetWord()); + printf("\n"); + } + } +} + + +void CInputScript::ParseStopSound() +{ + Control *ctrl; + + ctrl = new Control; + if (ctrl == NULL) { + outOfMemory = 1; + return; + } + ctrl->type = ctrlStopSound; + + program->addControlInCurrentFrame(ctrl); +} + + +void CInputScript::ParseShapeData(int getAlpha, int getStyles) +{ + int shapeRecord = 0; + + if (getStyles) { + // ShapeWithStyle + ParseFillStyle(getAlpha); + ParseLineStyle(getAlpha); + } + + InitBits(); + m_nFillBits = (U16) GetBits(4); + m_nLineBits = (U16) GetBits(4); + + do { + shapeRecord = ParseShapeRecord(getAlpha); + } while (shapeRecord); +} + +int +CInputScript::ParseShapeRecord(long getAlpha) +{ + // Determine if this is an edge. + BOOL isEdge = (BOOL) GetBits(1); + + if (!isEdge) + { + // Handle a state change + U16 flags = (U16) GetBits(5); + + // Are we at the end? + if (flags == 0) + { + // End of shape + return 0; + } + + // Process a move to. + if (flags & flagsMoveTo) + { + U16 nBits = (U16) GetBits(5); + GetSBits(nBits); + GetSBits(nBits); + } + + // Get new fill info. + if (flags & flagsFill0) + { + GetBits(m_nFillBits); + } + if (flags & flagsFill1) + { + GetBits(m_nFillBits); + } + + // Get new line info + if (flags & flagsLine) + { + GetBits(m_nLineBits); + } + + // Check to get a new set of styles for a new shape layer. + if (flags & flagsNewStyles) + { + // Parse the style. + ParseFillStyle(getAlpha); + ParseLineStyle(getAlpha); + + InitBits(); // Bug ! + + // Reset. + m_nFillBits = (U16) GetBits(4); + m_nLineBits = (U16) GetBits(4); + } + + return flags & flagsEndShape ? 0 : 1; + } + else + { + if (GetBits(1)) + { + // Handle a line + U16 nBits = (U16) GetBits(4) + 2; // nBits is biased by 2 + + // Save the deltas + if (GetBits(1)) + { + // Handle a general line. + GetSBits(nBits); + GetSBits(nBits); + } + else + { + // Handle a vert or horiz line. + GetBits(1); + GetSBits(nBits); + } + } + else + { + // Handle a curve + U16 nBits = (U16) GetBits(4) + 2; // nBits is biased by 2 + + // Get the control + GetSBits(nBits); + GetSBits(nBits); + + // Get the anchor + GetSBits(nBits); + GetSBits(nBits); + } + + return 1; + } +} + + +void CInputScript::ParseFillStyle(long getAlpha) + // +{ + U16 i = 0; + FillType type; + Matrix matrix; + + // Get the number of fills. + U16 nFills = GetByte(); + + // Do we have a larger number? + if (nFills == 255) + { + // Get the larger number. + nFills = GetWord(); + } + + // Get each of the fill style. + for (i = 0; i < nFills; i++) + { + U16 fillStyle = GetByte(); + + type = (FillType) fillStyle; + + printf("fillstyle: type=%d\n",defs[i].type); + if (fillStyle & 0x10) + { + U16 nbGradients; + + type = (FillType) (fillStyle & 0x12); + + // Get the gradient matrix. + GetMatrix(&matrix); + + // Get the number of colors. + nbGradients = GetByte(); + + // Get each of the colors. + for (U16 j = 0; j < nbGradients; j++) + { + GetByte(); + GetByte(); + GetByte(); + GetByte(); + if (getAlpha) { + GetByte(); + } + } + } + else if (fillStyle & 0x40) + { + type = (FillType) (fillStyle & 0x41); + + // Get the bitmapId + GetWord(); + + // Get the bitmap matrix. + GetMatrix(&matrix); + } + else + { + type = (FillType) 0; + + // A solid color + GetByte(); + GetByte(); + GetByte(); + if (getAlpha) { + GetByte(); + } + + printf("fillstyle: %x %x %x %x\n", + defs[i].color.red, + defs[i].color.green, + defs[i].color.blue, + defs[i].color.alpha); + } + } +} + +void CInputScript::ParseLineStyle(long getAlpha) +{ + long i; + + // Get the number of lines. + U16 nLines = GetByte(); + + // Do we have a larger number? + if (nLines == 255) + { + // Get the larger number. + nLines = GetWord(); + } + + // Get each of the line styles. + for (i = 0; i < nLines; i++) + { + GetWord(); + GetByte(); + GetByte(); + GetByte(); + if (getAlpha) { + GetByte(); + } + } +} + + +void CInputScript::ParseDefineShape(int level) +{ + Shape *shape; + Rect rect; + U32 tagid; + + tagid = (U32) GetWord(); + shape = new Shape(tagid,level); + if (shape == NULL) { + outOfMemory = 1; + return; + } + shape->dict = this; + + // Get the frame information. + GetRect(&rect); + + shape->setBoundingBox(rect); + + shape->file_ptr = (unsigned char*)malloc(m_tagEnd-m_filePos); + if (shape->file_ptr == NULL) { + outOfMemory = 1; + delete shape; + return; + } + memcpy((void*)shape->file_ptr,(void*)&m_fileBuf[m_filePos], m_tagEnd-m_filePos); + + shape->getStyles = 1; + shape->getAlpha = (level == 3); + + ParseShapeData(level == 3, 1); + + addCharacter(shape); +} + +void CInputScript::S_DumpImageGuts() +{ +#if 0 + U32 lfCount = 0; + printf("----- dumping image details -----"); + while (m_filePos < m_tagEnd) + { + if ((lfCount % 16) == 0) + { + fprintf(stdout, "\n"); + } + lfCount += 1; + fprintf(stdout, "%02x ", GetByte()); + } + fprintf(stdout, "\n"); +#endif +} + +void CInputScript::ParseDefineBits() +{ + Bitmap *bitmap; + U32 tagid = (U32) GetWord(); + int status; + + bitmap = new Bitmap(tagid,1); + if (bitmap == NULL) { + outOfMemory = 1; + return; + } + + status = bitmap->buildFromJpegAbbreviatedData(&m_fileBuf[m_filePos]); + + if (status < 0) { + fprintf(stderr,"Unable to read JPEG data\n"); + delete bitmap; + return; + } + + addCharacter(bitmap); +} + + +void CInputScript::ParseDefineBitsJPEG2() +{ + Bitmap *bitmap; + U32 tagid = (U32) GetWord(); + int status; + + bitmap = new Bitmap(tagid,2); + if (bitmap == NULL) { + outOfMemory = 1; + return; + } + + status = bitmap->buildFromJpegInterchangeData(&m_fileBuf[m_filePos], 0, 0); + + if (status < 0) { + fprintf(stderr,"Unable to read JPEG data\n"); + delete bitmap; + return; + } + + addCharacter(bitmap); +} + +void CInputScript::ParseDefineBitsJPEG3() +{ + Bitmap *bitmap; + U32 tagid = (U32) GetWord(); + int status; + long offset; + + printf("tagDefineBitsJPEG3 \ttagid %-5u\n", tagid); + + bitmap = new Bitmap(tagid,3); + if (bitmap == NULL) { + outOfMemory = 1; + return; + } + + offset = GetDWord(); // Not in the specs !!!! + + status = bitmap->buildFromJpegInterchangeData(&m_fileBuf[m_filePos], 1, offset); + if (status < 0) { + fprintf(stderr,"Unable to read JPEG data\n"); + delete bitmap; + return; + } + + addCharacter(bitmap); +} + + +void CInputScript::ParseDefineBitsLossless(int level) +{ + Bitmap *bitmap; + U32 tagid = (U32) GetWord(); + int status; + int tableSize; + + bitmap = new Bitmap(tagid,0); + if (bitmap == NULL) { + outOfMemory = 1; + return; + } + + int format = GetByte(); + int width = GetWord(); + int height = GetWord(); + + tableSize = 0; + + if (format == 3) { + tableSize = GetByte(); + } + + status = bitmap->buildFromZlibData(&m_fileBuf[m_filePos], width, height, format, tableSize, level == 2); + + if (status < 0) { + fprintf(stderr,"Unable to read ZLIB data\n"); + delete bitmap; + return; + } + + addCharacter(bitmap); +} + +void CInputScript::ParseJPEGTables() +{ + Bitmap::readJpegTables(&m_fileBuf[m_filePos]); +} + + +ButtonRecord * CInputScript::ParseButtonRecord(long getCxform) +{ + U16 state; + ButtonRecord *br; + long tagid; + Matrix matrix; + long layer; + Cxform *cxform; + + state = (U16) GetByte(); + + if (state == 0) return 0; + + br = new ButtonRecord; + if (br == NULL) { + outOfMemory = 1; + return 0; + } + + tagid = GetWord(); + layer = GetWord(); + GetMatrix(&matrix); + + if (br) { + br->state = (ButtonState) state; + br->character = getCharacter(tagid); + br->layer = layer; + br->cxform = 0; + br->buttonMatrix = matrix; + } + + if (getCxform) { + cxform = new Cxform; + GetCxform(cxform, true); + if (br) { + br->cxform = cxform; + if (cxform == NULL) { + outOfMemory = 1; + } + } + } + + return br; +} + +ActionRecord * CInputScript::ParseActionRecord() +{ + U8 action; + U16 length = 0; + char *url, *target, *label; + long frameIndex, skipCount; + ActionRecord *ar; + + action = GetByte(); + if (action == 0) return 0; + + ar = new ActionRecord; + if (ar == NULL) { + outOfMemory = 1; + return 0; + } + + ar->action = (Action)action; + + if (action & 0x80) { + length = GetWord(); + } + + switch (action) { + case ActionGotoFrame: + frameIndex = GetWord(); + if (ar) { + ar->frameIndex = frameIndex; + } + break; + case ActionGetURL: + url = GetString(); + target = GetString(); + if (ar) { + ar->url = strdup(url); + ar->target = strdup(target); + } + break; + case ActionWaitForFrame: + frameIndex = GetWord(); + skipCount = GetByte(); + if (ar) { + ar->frameIndex = frameIndex; + ar->skipCount = skipCount; + } + break; + case ActionSetTarget: + target = strdup(GetString()); + if (ar) { + ar->target = target; + } + break; + case ActionGoToLabel: + label = GetString(); + if (ar) { + ar->frameLabel = strdup(label); + } + break; + default: + while (length--) { + GetByte(); + } + break; + } + + return ar; +} + +void CInputScript::ParseDefineButton() +{ + Button *button; + ButtonRecord *buttonRecord; + ActionRecord *actionRecord; + + U32 tagid = (U32) GetWord(); + + button = new Button(tagid); + if (button == NULL) { + outOfMemory = 1; + return; + } + + do { + buttonRecord = ParseButtonRecord(); + if (buttonRecord) { + button->addButtonRecord( buttonRecord ); + } + if (outOfMemory) { + return; + } + } while (buttonRecord); + + do { + actionRecord = ParseActionRecord(); + if (actionRecord) { + button->addActionRecord( actionRecord ); + } + if (outOfMemory) { + return; + } + } while (actionRecord); + + addCharacter(button); +} + + +void CInputScript::ParseDefineButton2() +{ + Button *button; + ButtonRecord *buttonRecord; + ActionRecord *actionRecord; + U16 transition; + U16 offset; + U8 menu; + + U32 tagid = (U32) GetWord(); + + button = new Button(tagid); + + if (button == NULL) { + outOfMemory = 1; + return; + } + + menu = GetByte(); + + offset = GetWord(); + + do { + buttonRecord = ParseButtonRecord(true); + if (buttonRecord) { + button->addButtonRecord( buttonRecord ); + } + if (outOfMemory) { + return; + } + } while (buttonRecord); + + while (offset) { + offset = GetWord(); + + transition = GetWord(); + + do { + actionRecord = ParseActionRecord(); + if (actionRecord) { + button->addActionRecord( actionRecord ); + } + if (outOfMemory) { + return; + } + } while (actionRecord); + + button->addCondition( transition ); + } + + addCharacter(button); +} + + +void CInputScript::ParseDefineFont() +{ + SwfFont *font = 0; + U32 tagid = (U32) GetWord(); + long start; + long nb,n; + long offset; + long *offsetTable = 0; + Shape *shapes = 0; + + font = new SwfFont(tagid); + if (font == NULL) { + outOfMemory = 1; + return; + } + start = m_filePos; + + offset = GetWord(); + nb = offset/2; + offsetTable = new long[nb]; + if (offsetTable == NULL) { + goto memory_error; + } + offsetTable[0] = offset; + + for(n=1; nsetFontShapeTable(shapes,nb); + + delete[] offsetTable; + + addCharacter(font); + return; + +memory_error: + outOfMemory = 1; + if (offsetTable) delete offsetTable; + if (font) delete font; + if (shapes) delete[] shapes; +} + + +void CInputScript::ParseDefineMorphShape() +{ + U32 tagid = (U32) GetWord(); + + tagid = tagid; + printf("tagDefineMorphShape \ttagid %-5u\n", tagid); +} + +void CInputScript::ParseDefineFontInfo() +{ + SwfFont *font; + U32 tagid = (U32) GetWord(); + long nameLen; + char *name; + long n,nb; + FontFlags flags; + long *lut; + + font = (SwfFont *)getCharacter(tagid); + + if (font == NULL) { + outOfMemory = 1; + return; + } + + nameLen = GetByte(); + name = new char[nameLen+1]; + if (name == NULL) { + outOfMemory = 1; + return; + } + for(n=0; n < nameLen; n++) + { + name[n] = GetByte(); + } + name[n]=0; + + font->setFontName(name); + + delete name; + + flags = (FontFlags)GetByte(); + + font->setFontFlags(flags); + + nb = font->getNbGlyphs(); + + lut = new long[nb]; + if (lut == NULL) { + outOfMemory = 1; + delete font; + return; + } + + for(n=0; n < nb; n++) + { + if (flags & fontWideCodes) { + lut[n] = GetWord(); + } else { + lut[n] = GetByte(); + } + } + + font->setFontLookUpTable(lut); +} + + + + + +void CInputScript::ParseDefineFont2() +{ + int n; + U32 tagid = (U32) GetWord(); + FontFlags flags; + char *name; + long nameLen; + long fontGlyphCount; + long *offsetTable = NULL; + Shape *shapes = NULL; + long start; + SwfFont *font; + long *lut = NULL; + + font = new SwfFont(tagid); + if (font == NULL) { + goto memory_error; + } + + flags = (FontFlags)GetWord(); + + font->setFontFlags(flags); + + nameLen = GetByte(); + name = new char[nameLen+1]; + if (name == NULL) { + goto memory_error; + } + for(n=0; n < nameLen; n++) + { + name[n] = GetByte(); + } + name[n]=0; + + font->setFontName(name); + + delete name; + + fontGlyphCount = GetWord(); + + start = m_filePos; + + offsetTable = new long[fontGlyphCount]; + if (offsetTable == NULL) { + goto memory_error; + } + for (n=0; nsetFontShapeTable(shapes,fontGlyphCount); + + lut = new long[fontGlyphCount]; + if (lut == NULL) { + goto memory_error; + } + + for(n=0; n < fontGlyphCount; n++) + { + if (flags & 4) { + lut[n] = GetWord(); + } else { + lut[n] = GetByte(); + } + } + + font->setFontLookUpTable(lut); + + delete offsetTable; + + addCharacter(font); + + // This is an incomplete parsing + return; + +memory_error: + outOfMemory = 1; + if (font) delete font; + if (offsetTable) delete offsetTable; + if (lut) delete lut; + if (shapes) delete[] shapes; +} + +TextRecord * CInputScript::ParseTextRecord(int hasAlpha) +{ + TextRecord *tr; + TextFlags flags; + + flags = (TextFlags) GetByte(); + if (flags == 0) return 0; + + tr = new TextRecord; + if (tr == NULL) { + outOfMemory = 1; + return 0; + } + + tr->flags = flags; + + if (flags & isTextControl) { + if (flags & textHasFont) { + long fontId; + + fontId = GetWord(); + tr->font = (SwfFont *)getCharacter(fontId); + } + if (flags & textHasColor) { + tr->color.red = GetByte(); + tr->color.green = GetByte(); + tr->color.blue = GetByte(); + if (hasAlpha) { + tr->color.alpha = GetByte(); + } else { + tr->color.alpha = ALPHA_OPAQUE; + } + } + if (flags & textHasXOffset) { + tr->xOffset = GetWord(); + } + if (flags & textHasYOffset) { + tr->yOffset = GetWord(); + } + if (flags & textHasFont) { + tr->fontHeight = GetWord(); + } + tr->nbGlyphs = GetByte(); + } else { + tr->flags = (TextFlags)0; + tr->nbGlyphs = (long)flags; + } + + tr->glyphs = new Glyph[ tr->nbGlyphs ]; + if (tr->glyphs == NULL) { + outOfMemory = 1; + delete tr; + return 0; + } + + InitBits(); + for (int g = 0; g < tr->nbGlyphs; g++) + { + tr->glyphs[g].index = GetBits(m_nGlyphBits); + tr->glyphs[g].xAdvance = GetBits(m_nAdvanceBits); + } + + return tr; +} + +void CInputScript::ParseDefineText(int hasAlpha) +{ + Text *text; + TextRecord *textRecord; + Matrix m; + Rect rect; + U32 tagid = (U32) GetWord(); + + text = new Text(tagid); + if (text == NULL) { + outOfMemory = 1; + return; + } + + GetRect(&rect); + text->setTextBoundary(rect); + + GetMatrix(&m); + text->setTextMatrix(m); + + m_nGlyphBits = GetByte(); + m_nAdvanceBits = GetByte(); + + do { + textRecord = ParseTextRecord(hasAlpha); + if (textRecord) { + text->addTextRecord( textRecord ); + } + if (outOfMemory) { + delete text; + return; + } + if (m_filePos >= m_tagEnd) break; + } while (textRecord); + + addCharacter(text); +} + + +void CInputScript::ParseDefineSound() +{ + Sound *sound; + U32 tagid = (U32) GetWord(); + long nbSamples; + long flags; + char *buffer; + + sound = new Sound(tagid); + + flags = GetByte(); + sound->setSoundFlags(flags); + + nbSamples = GetDWord(); + buffer = sound->setNbSamples(nbSamples); + if (buffer == NULL) { + outOfMemory = 1; + delete sound; + return; + } + + if (flags & soundIsADPCMCompressed) { + Adpcm *adpcm; + + adpcm = new Adpcm( &m_fileBuf[m_filePos] , flags & soundIsStereo ); + + adpcm->Decompress((short *)buffer, nbSamples); + + delete adpcm; + } else { + memcpy(buffer, &m_fileBuf[m_filePos], m_tagLen-5); + } + + addCharacter(sound); +} + + +void CInputScript::ParseDefineButtonSound() +{ + U32 tagid = (U32) GetWord(); + Button *button; + + tagid = tagid; + + printf("tagDefineButtonSound \ttagid %-5u\n", tagid); + + button = (Button *)getCharacter(tagid); + + if (button == 0) { + printf(" Couldn't find Button id %d\n", tagid); + return; + } + + // step through for button states + for (int i = 0; i < 4; i++) + { + Sound *sound; + U32 soundTag = GetWord(); + + sound = (Sound *)getCharacter(soundTag); + + if (sound) { + button->setButtonSound(sound,i); + } else if (soundTag) { + printf(" Couldn't find Sound id %d\n", soundTag); + } + + switch (i) + { + case 0: + printf("upState \ttagid %-5u\n", soundTag); + break; + case 1: + printf("overState \ttagid %-5u\n", soundTag); + break; + case 2: + printf("downState \ttagid %-5u\n", soundTag); + break; + } + + if (soundTag) + { + U32 code = GetByte(); + printf("sound code %u", code); + + if ( code & soundHasInPoint ) + printf(" inpoint %u", GetDWord()); + if ( code & soundHasOutPoint ) + printf(" outpoint %u", GetDWord()); + if ( code & soundHasLoops ) + printf(" loops %u", GetWord()); + + printf("\n"); + if ( code & soundHasEnvelope ) + { + int points = GetByte(); + + for ( int p = 0; p < points; p++ ) + { + printf("\n"); + printf("mark44 %u", GetDWord()); + printf(" left chanel %u", GetWord()); + printf(" right chanel %u", GetWord()); + printf("\n"); + } + } + } + if (m_filePos == m_tagEnd) break; + } +} + +void CInputScript::ParseSoundStreamHead() +{ + int mixFormat = GetByte(); + + // The stream settings + int format = GetByte(); + int nSamples = GetWord(); + + mixFormat = mixFormat; + format = format; + nSamples = nSamples; + + printf("tagSoundStreamHead \tmixFrmt %-3u frmt %-3u nSamples %-5u\n", mixFormat, format, nSamples); +} + +void CInputScript::ParseSoundStreamHead2() +{ + int mixFormat = GetByte(); + + // The stream settings + int format = GetByte(); + int nSamples = GetWord(); + + mixFormat = mixFormat; + format = format; + nSamples = nSamples; + + //printf("tagSoundStreamHead2 \tmixFormat %-3u format %-3u nSamples %-5u\n", mixFormat, format, nSamples); +} + +void CInputScript::ParseSoundStreamBlock() +{ + printf("tagSoundStreamBlock\n"); +} + +void CInputScript::ParseDefineButtonCxform() +{ + ButtonRecord *br; + Button *button; + U32 tagid = (U32) GetWord(); + + button = (Button *)getCharacter(tagid); + + for (br = button->getButtonRecords(); br; br = br->next) + { + br->cxform = new Cxform; + GetCxform(br->cxform, false); + } +} + +void CInputScript::ParseNameCharacter() +{ + U32 tagid = (U32) GetWord(); + char *label = strdup(GetString()); + + nameCharacter(tagid, label); +} + + +void CInputScript::ParseFrameLabel() +{ + char *label = strdup(GetString()); + program->setCurrentFrameLabel(label); +} + + +void CInputScript::ParseDefineMouseTarget() +{ + printf("tagDefineMouseTarget\n"); +} + + +void CInputScript::ParseDefineSprite() +{ + Sprite *sprite; + Program *prg; + int status; + + U32 tagid = (U32) GetWord(); + U32 frameCount = (U32) GetWord(); + + if (frameCount == 0) return; + + printf("tagDefineSprite \ttagid %-5u \tframe count %-5u\n", tagid, frameCount); + + sprite = new Sprite(program->movie, tagid, frameCount); + if (sprite == NULL) { + outOfMemory = 1; + return; + } + if (sprite->getProgram() == NULL) { + delete sprite; + outOfMemory = 1; + return; + } + + prg = sprite->getProgram(); + + // Set current program + program = prg; + + ParseTags(&status); + + if (outOfMemory) { + delete sprite; + return; + } + + addCharacter(sprite); +} + + +void CInputScript::ParseUnknown(long code, long len) +{ + printf("Unknown Tag : %d - Length = %d\n", code, len); +} + + +void +CInputScript::ParseTags(int *status) + // Parses the tags within the file. +{ + + // Initialize the end of frame flag. + BOOL atEnd = false; + + // Loop through each tag. + while (!atEnd) + { + U32 here; + + // Get the current tag. + U16 code = GetTag(); + + if (code == notEnoughData) { + m_filePos = m_tagStart; + *status |= FLASH_PARSE_NEED_DATA; + return; + } + + //printf("Code %d, tagLen %8u \n", code, m_tagLen); + + here = m_filePos; + + // Get the tag ending position. + U32 tagEnd = m_tagEnd; + + if (m_tagEnd > m_actualSize) { + m_filePos = m_tagStart; + *status |= FLASH_PARSE_NEED_DATA; + return; + } + + switch (code) + { + case stagProtect: + break; + + case stagEnd: + + // We reached the end of the file. + atEnd = true; + + printf("End of Movie\n"); + + break; + + case stagShowFrame: + + // Validate frame + program->validateLoadingFrame(); + *status |= FLASH_PARSE_WAKEUP; + + break; + + case stagFreeCharacter: + ParseFreeCharacter(); + break; + + case stagPlaceObject: + ParsePlaceObject(); + break; + + case stagPlaceObject2: + ParsePlaceObject2(); + break; + + case stagRemoveObject: + ParseRemoveObject(); + break; + + case stagRemoveObject2: + ParseRemoveObject2(); + break; + + case stagSetBackgroundColor: + ParseSetBackgroundColor(); + break; + + case stagDoAction: + ParseDoAction(); + break; + + case stagStartSound: + ParseStartSound(); + break; + + case stagStopSound: + ParseStopSound(); + break; + + case stagDefineShape: + ParseDefineShape(1); + break; + + case stagDefineShape2: + ParseDefineShape(2); + break; + + case stagDefineShape3: + ParseDefineShape(3); + break; + + case stagDefineBits: + ParseDefineBits(); + break; + + case stagDefineBitsJPEG2: + ParseDefineBitsJPEG2(); + break; + + case stagDefineBitsJPEG3: + ParseDefineBitsJPEG3(); + break; + + case stagDefineBitsLossless: + ParseDefineBitsLossless(1); + break; + + case stagDefineBitsLossless2: + ParseDefineBitsLossless(2); + break; + + case stagJPEGTables: + ParseJPEGTables(); + break; + + case stagDefineButton: + ParseDefineButton(); + break; + + case stagDefineButton2: + ParseDefineButton2(); + break; + + case stagDefineFont: + ParseDefineFont(); + break; + + case stagDefineMorphShape: + ParseDefineMorphShape(); + break; + + case stagDefineFontInfo: + ParseDefineFontInfo(); + break; + + case stagDefineText: + ParseDefineText(0); + break; + + case stagDefineText2: + ParseDefineText(1); + break; + + case stagDefineSound: + ParseDefineSound(); + break; + + case stagDefineButtonSound: + ParseDefineButtonSound(); + break; + + case stagSoundStreamHead: + ParseSoundStreamHead(); + break; + + case stagSoundStreamHead2: + ParseSoundStreamHead2(); + break; + + case stagSoundStreamBlock: + ParseSoundStreamBlock(); + break; + + case stagDefineButtonCxform: + ParseDefineButtonCxform(); + break; + + case stagDefineSprite: + Program *save; + + save = program; + ParseDefineSprite(); + program->rewindMovie(); + program = save; + break; + + case stagNameCharacter: + ParseNameCharacter(); + break; + + case stagFrameLabel: + ParseFrameLabel(); + break; + + case stagDefineFont2: + ParseDefineFont2(); + break; + + default: + ParseUnknown(code, m_tagLen); + break; + } + + //printf("Bytes read = %d\n", m_filePos-here); + + // Increment the past the tag. + m_filePos = tagEnd; + + if (outOfMemory) { + fprintf(stderr,"Flash: Out of memory\n"); + *status |= FLASH_PARSE_OOM; + return; + } + } + + program->validateLoadingFrame(); + *status |= FLASH_PARSE_EOM; +} + +int +CInputScript::ParseData(FlashMovie *movie, char * data, long size) +{ + int status = FLASH_PARSE_ERROR; + + m_fileBuf = (unsigned char *)data; + m_actualSize = size; + + if (needHeader) { + + // Do we have sufficient data to read the header ? + if (size < 21) { + return FLASH_PARSE_NEED_DATA; // No, need more data + } + + needHeader = 0; // Yes + + U8 fileHdr[8]; + + memcpy(fileHdr,data,8); + + // Verify the header and get the file size. + if (fileHdr[0] != 'F' || fileHdr[1] != 'W' || fileHdr[2] != 'S' ) + { + //fprintf(stderr, "Not a Flash File.\n"); + return FLASH_PARSE_ERROR; // Error + } + else + { + // Get the file version. + m_fileVersion = (U16) fileHdr[3]; + } + + // Get the file size. + m_fileSize = (U32) fileHdr[4] + | ((U32) fileHdr[5] << 8) + | ((U32) fileHdr[6] << 16) + | ((U32) fileHdr[7] << 24); + + // Verify the minimum length of a Flash file. + if (m_fileSize < 21) + { + //printf("ERROR: File size is too short\n"); + return FLASH_PARSE_ERROR; // Error + } + + // Set the file position past the header and size information. + m_filePos = 8; + + // Get the frame information. + GetRect(&frameRect); + + frameRate = GetWord() >> 8; + + frameCount = GetWord(); + + program = new Program(movie, frameCount); + + if (program == NULL || program->totalFrames == 0) { + return FLASH_PARSE_ERROR; + } + + status |= FLASH_PARSE_START; + } + + ParseTags(&status); + + return status; +} + + diff --git a/core/multimedia/opieplayer/libflash/script.h b/core/multimedia/opieplayer/libflash/script.h new file mode 100644 index 0000000..a41c47e --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/script.h @@ -0,0 +1,144 @@ +#ifndef _SCRIPT_H_ +#define _SCRIPT_H_ + +// SWF file parser. +// +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +// Input script object definition. +////////////////////////////////////////////////////////////////////// + +// An input script object. This object represents a script created from +// an external file that is meant to be inserted into an output script. +struct CInputScript : public Dict +{ + int level; + struct CInputScript *next; + + Program *program; // Current parsed program + + // Memory fences + int outOfMemory; + + //Flash info + long frameRate; + long frameCount; + Rect frameRect; + + // Pointer to file contents buffer. + U8 *m_fileBuf; + + // File state information. + U32 m_filePos; + U32 m_fileSize; + U32 m_actualSize; + U32 m_fileStart; + U16 m_fileVersion; + + int needHeader; + + // Bit Handling + S32 m_bitPos; + U32 m_bitBuf; + + // Tag parsing information. + U32 m_tagStart; + U32 m_tagEnd; + U32 m_tagLen; + + // Parsing information. + S32 m_nFillBits; + S32 m_nLineBits; + S32 m_nGlyphBits; + S32 m_nAdvanceBits; + + // Set to true if we wish to dump all contents long form + U32 m_dumpAll; + + // if set to true will dump image guts (i.e. jpeg, zlib, etc. data) + U32 m_dumpGuts; + + // Handle to output file. + FILE *m_outputFile; + + // Constructor/destructor. + CInputScript(int level = 0); + ~CInputScript(); + + // Tag scanning methods. + U16 GetTag(void); + U8 GetByte(void); + U16 GetWord(void); + U32 GetDWord(void); + void GetRect(Rect *r); + void GetMatrix(Matrix *matrix); + + void GetCxform(Cxform *cxform, BOOL hasAlpha); + char *GetString(void); + + // Routines for reading arbitrary sized bit fields from the stream. + // Always call start bits before gettings bits and do not intermix + // these calls with GetByte, etc... + void InitBits(); + S32 GetSBits(S32 n); + U32 GetBits(S32 n); + + // Tag subcomponent parsing methods + void ParseFillStyle(long getAlpha = 0); + void ParseLineStyle(long getAlpha = 0); + int ParseShapeRecord(long getAlpha = 0); + ButtonRecord * ParseButtonRecord(long getCxform = 0); + ActionRecord * ParseActionRecord(); + TextRecord * ParseTextRecord(int hasAlpha = 0); + void ParseShapeData(int getAlpha, int getStyles); + + // Parsing methods. + void ParseEnd(); // 00: stagEnd + void ParseShowFrame(U32 frame, U32 offset); // 01: stagShowFrame + void ParseDefineShape(int level); // 02: stagDefineShape + void ParseFreeCharacter(); // 03: stagFreeCharacter + void ParsePlaceObject(); // 04: stagPlaceObject + void ParseRemoveObject(); // 05: stagRemoveObject + void ParseDefineBits(); // 06: stagDefineBits + void ParseDefineButton(); //x 07: stagDefineButton + void ParseJPEGTables(); // 08: stagJPEGTables + void ParseSetBackgroundColor(); // 09: stagSetBackgroundColor + void ParseDefineFont(); //x 10: stagDefineFont + void ParseDefineText(int hasAplha); //x 11: stagDefineText 33: stagDefineText2 + void ParseDoAction(); // 12: stagDoAction + void ParseDefineFontInfo(); //x 13: stagDefineFontInfo + void ParseDefineSound(); // 14: stagDefineSound + void ParseStartSound(); // 15: stagStartSound + void ParseStopSound(); // 16: stagStopSound + void ParseDefineButtonSound(); // 17: stagDefineButtonSound + void ParseSoundStreamHead(); // 18: stagSoundStreamHead + void ParseSoundStreamBlock(); // 19: stagSoundStreamBlock + void ParseDefineBitsLossless(int level); // 20: stagDefineBitsLossless 36: stagDefineBitsLossless2 + void ParseDefineBitsJPEG2(); // 21: stagDefineBitsJPEG2 + void ParseDefineButtonCxform(); // 23: stagDefineButtonCxform + void ParseProtect(); // 24: stagProtect + void ParsePlaceObject2(); // 26: stagPlaceObject2 + void ParseRemoveObject2(); // 28: stagRemoveObject2 + void ParseDefineButton2(); //x 34: stagDefineButton2 + void ParseDefineBitsJPEG3(); // 35: stagDefineBitsJPEG3 + void ParseDefineMouseTarget(); // 38: stagDefineMouseTarget + void ParseDefineSprite(); //x 39: stagDefineSprite + void ParseNameCharacter(); // 40: stagNameCharacter + void ParseFrameLabel(); // 43: stagFrameLabel + void ParseSoundStreamHead2(); // 45: stagSoundStreamHead2 + void ParseDefineMorphShape(); //x 46: stagDefineMorphShape + void ParseDefineFont2(); //x 48: stagDefineFont2 + void ParseUnknown(long,long); + + void ParseTags(int *); + int ParseData(FlashMovie *movie, char * data, long size); + void S_DumpImageGuts(); + +#ifdef DUMP + long save(char *filenam); +#endif +}; + + +#endif /* _SCRIPT_H_ */ diff --git a/core/multimedia/opieplayer/libflash/shape.cc b/core/multimedia/opieplayer/libflash/shape.cc new file mode 100644 index 0000000..0d8df93 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/shape.cc @@ -0,0 +1,1205 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +#define PRINT 0 + +#define ABS(v) ((v) < 0 ? -(v) : (v)) + +static void prepareStyles(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, FillStyleDef *f, long n); + +static void clearStyles(GraphicDevice *gd, FillStyleDef *f, long n); + +static void drawShape(GraphicDevice *gd, Matrix *matrix1, Cxform *cxform, Shape *shape, + ShapeAction shapeAction, void *id,ScanLineFunc scan_line_func); + +// Constructor + +Shape::Shape(long id, int level) : Character(ShapeType, id) +{ + defLevel = level; + + defaultFillStyle.type = f_Solid; + defaultFillStyle.color.red = 0; + defaultFillStyle.color.green = 0; + defaultFillStyle.color.blue = 0; + defaultFillStyle.color.alpha = ALPHA_OPAQUE; + + defaultLineStyle.width = 0; + + // This is to force a first update + lastMat.a = 0; + lastMat.d = 0; + shape_size += sizeof(Shape); + shape_nb ++; + + file_ptr = NULL; + getStyles = 0; + getAlpha = 0; +} + +Shape::~Shape() +{ + if (file_ptr) { + free(file_ptr); + } +} + +void +Shape::setBoundingBox(Rect rect) +{ + boundary = rect; +} + +void +Shape::getBoundingBox(Rect *bb, DisplayListEntry *e) +{ + *bb = boundary; +} + +int +Shape::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform) +{ + //printf("TagId = %d\n", getTagId()); + //if (getTagId() != 220) return 0; + + if (cxform) { + defaultFillStyle.color = cxform->getColor(gd->getForegroundColor()); + } else { + defaultFillStyle.color = gd->getForegroundColor(); + } + defaultFillStyle.color.pixel = gd->allocColor(defaultFillStyle.color); + + drawShape(gd, matrix, cxform, this, ShapeDraw, NULL, 0); + return 0; +} + +void +Shape::getRegion(GraphicDevice *gd, Matrix *matrix, void *id, ScanLineFunc scan_line_func) +{ + gd->setClipping(0); + drawShape(gd,matrix,0,this,ShapeGetRegion,id,scan_line_func); + gd->setClipping(1); +} + +/************************************************************************/ + +/* create a new path */ + +static void newPath(ShapeParser *shape, + long x, long y) +{ + Path *p; + long x1,y1; + + p=&shape->curPath; + + x1 = shape->matrix->getX(x, y); + y1 = shape->matrix->getY(x, y); + + p->lastX = x1; + p->lastY = y1; + + p->nb_edges = 0; + p->nb_segments = 0; +} + + +static void addSegment1(ShapeParser *shape, + long x, long y, + FillStyleDef *f0, + FillStyleDef *f1, + LineStyleDef *l) +{ + Path *p; + p=&shape->curPath; + + if (l) { + /* a line is defined ... it will be drawn later */ + LineSegment *ls; + + ls = new LineSegment; + if (ls != NULL) { + ls->l = l; + ls->x1 = p->lastX; + ls->y1 = p->lastY; + ls->x2 = x; + ls->y2 = y; + ls->first = (p->nb_segments == 0); + ls->next = NULL; + if (shape->last_line == NULL) { + shape->first_line = ls; + } else { + shape->last_line->next = ls; + } + shape->last_line = ls; + } + } + + /* anti antialiasing not needed if line */ + if (!shape->reverse) { + shape->gd->addSegment(p->lastX,p->lastY,x,y,f0,f1,l ? 0 : 1); + } else { + shape->gd->addSegment(p->lastX,p->lastY,x,y,f1,f0,l ? 0 : 1); + } + + p->lastX = x; + p->lastY = y; + + p->nb_segments++; +} + + +static void addLine(ShapeParser *shape, long x, long y, + FillStyleDef *f0, + FillStyleDef *f1, + LineStyleDef *l) +{ + long x1,y1; + Path *p; + + p=&shape->curPath; + + x1 = shape->matrix->getX(x, y); + y1 = shape->matrix->getY(x, y); + + addSegment1(shape,x1,y1,f0,f1,l); + + p->nb_edges++; +} + + +// This is based on Divide and Conquer algorithm. + +#define BFRAC_BITS 0 +#define BFRAC (1 << BFRAC_BITS) + +static void +bezierBuildPoints (ShapeParser *s, + int subdivisions, + long a1X, long a1Y, + long cX, long cY, + long a2X, long a2Y) +{ + long c1X,c1Y; + long c2X,c2Y; + long X,Y; + long xmin,ymin,xmax,ymax; + + if (subdivisions != 0) { + + /* find the bounding box */ + + if (a1X < cX) { + xmin = a1X; + xmax = cX; + } else { + xmin = cX; + xmax = a1X; + } + if (a2X < xmin) xmin = a2X; + if (a2X > xmax) xmax = a2X; + + if (a1Y < cY) { + ymin = a1Y; + ymax = cY; + } else { + ymin = cY; + ymax = a1Y; + } + if (a2Y < ymin) ymin = a2Y; + if (a2Y > ymax) ymax = a2Y; + + if (((xmax - xmin) + (ymax - ymin)) >= (BFRAC*FRAC*2)) { + // Control point 1 + c1X = (a1X+cX) >> 1; + c1Y = (a1Y+cY) >> 1; + + // Control point 2 + c2X = (a2X+cX) >> 1; + c2Y = (a2Y+cY) >> 1; + + // New point + X = (c1X+c2X) >> 1; + Y = (c1Y+c2Y) >> 1; + + subdivisions--; + + bezierBuildPoints(s, subdivisions, + a1X, a1Y, c1X, c1Y, X, Y); + bezierBuildPoints(s, subdivisions, + X, Y, c2X, c2Y, a2X, a2Y); + + return; + } + } + + addSegment1(s, (a2X+(BFRAC/2)) >> BFRAC_BITS, + (a2Y+(BFRAC/2)) >> BFRAC_BITS, s->f0, s->f1, s->l); +} + +/* this code is broken, but useful to get something */ +static void flushPaths(ShapeParser *s) +{ + LineSegment *ls; + LineStyleDef *l; + long nx,ny,nn,w; + GraphicDevice *gd = s->gd; + + /* draw the filled polygon */ + gd->drawPolygon(); + + /* draw the lines */ + ls = s->first_line; + if (ls != NULL) { + do { + l = ls->l; + +#if 0 + printf("line %d %d %d %d width=%d\n", + ls->x1, ls->y1, ls->x2, ls->y2, l->width); +#endif + + /* XXX: this width is false, but it is difficult (and expensive) + to have the correct one */ + w = ABS((long)(s->matrix->a * l->width)); + + if (w <= ((3*FRAC)/2)) { + w = FRAC; + } +#ifdef THIN_LINES + if (w <= ((3*FRAC)/2)) { + // draw the thin lines only in shapeAction == shapeDraw + if (gd->scan_line_func == NULL) { + gd->setForegroundColor(l->fillstyle.color); + gd->drawLine(ls->x1, ls->y1, ls->x2, ls->y2, w); + } + } else { +#else + { +#endif + /* compute the normal vector */ + + nx = -(ls->y2 - ls->y1); + ny = (ls->x2 - ls->x1); + + /* normalize & width */ + nn = 2 * (long) sqrt(nx * nx + ny * ny); + +#define UL ls->x1 + nx -ny, ls->y1 + ny +nx +#define UR ls->x2 + nx +ny, ls->y2 + ny -nx +#define LL ls->x1 - nx -ny, ls->y1 - ny +nx +#define LR ls->x2 - nx +ny, ls->y2 - ny -nx + + if (nn > 0) { + nx = (nx * w) / nn; + ny = (ny * w) / nn; + + /* top segment */ + gd->addSegment(UL, UR, NULL, &l->fillstyle, 1); + + /* bottom segment */ + gd->addSegment(LL, LR, &l->fillstyle, NULL, 1); + + /* right segment */ + gd->addSegment(UR, LR, &l->fillstyle, NULL, 1); + + /* left segment */ + gd->addSegment(UL, LL, NULL, &l->fillstyle, 1); + + /* draw the line polygon */ + gd->drawPolygon(); + } + } + + ls = ls->next; + } while (ls != NULL); + + /* delete the line structures */ + + ls = s->first_line; + while (ls != NULL) { + LineSegment *ls1; + ls1 = ls->next; + delete ls; + ls = ls1; + } + + /* reset the line pointers */ + s->first_line = NULL; + s->last_line = NULL; + } +} + + +static void addBezier(ShapeParser *shape, + long ctrlX1, long ctrlY1, + long newX1, long newY1, + FillStyleDef *f0, + FillStyleDef *f1, + LineStyleDef *l) +{ + long newX,newY,ctrlX,ctrlY; + Path *p; + + p=&shape->curPath; + + /* note: we do the matrix multiplication before calculating the + bezier points (faster !) */ + + ctrlX = shape->matrix->getX(ctrlX1, ctrlY1); + ctrlY = shape->matrix->getY(ctrlX1, ctrlY1); + newX = shape->matrix->getX(newX1, newY1); + newY = shape->matrix->getY(newX1, newY1); + + shape->f0 = f0; + shape->f1 = f1; + shape->l = l; + + bezierBuildPoints(shape, 3, + p->lastX<lastY<nb_edges++; +} + +/***********************************************************************/ + + +/* bit parser */ + +static void InitBitParser(struct BitParser *b,U8 *buf) +{ + b->ptr = buf; +} + +static void InitBits(struct BitParser *b) +{ + // Reset the bit position and buffer. + b->m_bitPos = 0; + b->m_bitBuf = 0; +} + + + +static inline U8 GetByte(struct BitParser *b) +{ + U8 v; + v = *b->ptr++; + return v; +} + +static inline U16 GetWord(struct BitParser *b) +{ + U8 *s; + U16 v; + s = b->ptr; + v = s[0] | ((U16) s[1] << 8); + b->ptr = s + 2; + return v; +} + +static inline U32 GetDWord(struct BitParser *b) +{ + U32 v; + U8 * s = b->ptr; + v = (U32) s[0] | ((U32) s[1] << 8) | + ((U32) s[2] << 16) | ((U32) s [3] << 24); + b->ptr = s + 4; + return v; +} + +static inline U32 GetBit (struct BitParser *b) +{ + U32 v; + S32 m_bitPos = b->m_bitPos; + U32 m_bitBuf = b->m_bitBuf; + + if (m_bitPos == 0) { + m_bitBuf = (U32)(*b->ptr++) << 24; + m_bitPos = 8; + } + + v = (m_bitBuf >> 31); + + m_bitPos--; + m_bitBuf <<= 1; + + b->m_bitPos = m_bitPos; + b->m_bitBuf = m_bitBuf; + + return v; +} + +static inline U32 GetBits (struct BitParser *b, int n) +{ + U32 v; + S32 m_bitPos = b->m_bitPos; + U32 m_bitBuf = b->m_bitBuf; + + if (n == 0) + return 0; + + while (m_bitPos < n) { + m_bitBuf |= (U32)(*b->ptr++) << (24 - m_bitPos); + m_bitPos += 8; + } + + v = m_bitBuf >> (32 - n); + m_bitBuf <<= n; + m_bitPos -= n; + + b->m_bitPos = m_bitPos; + b->m_bitBuf = m_bitBuf; + return v; +} + +// Get n bits from the string with sign extension. +static inline S32 GetSBits (struct BitParser *b,S32 n) +{ + // Get the number as an unsigned value. + S32 v = (S32) GetBits(b,n); + + // Is the number negative? + if (v & (1L << (n - 1))) + { + // Yes. Extend the sign. + v |= -1L << n; + } + + return v; +} + + + +/************************************************************************/ + +static void GetMatrix(BitParser *b, Matrix* mat) +{ + InitBits(b); + + // Scale terms + if (GetBit(b)) + { + int nBits = (int) GetBits(b,5); + mat->a = (float)(GetSBits(b,nBits))/(float)0x10000; + mat->d = (float)(GetSBits(b,nBits))/(float)0x10000; + } + else + { + mat->a = mat->d = 1.0; + } + + // Rotate/skew terms + if (GetBit(b)) + { + int nBits = (int)GetBits(b,5); + mat->c = (float)(GetSBits(b,nBits))/(float)0x10000; + mat->b = (float)(GetSBits(b,nBits))/(float)0x10000; + } + else + { + mat->b = mat->c = 0.0; + } + + // Translate terms + int nBits = (int) GetBits(b,5); + mat->tx = GetSBits(b,nBits); + mat->ty = GetSBits(b,nBits); +} + +static FillStyleDef * ParseFillStyle(ShapeParser *shape, long *n, long getAlpha) +{ + BitParser *b = &shape->bit_parser; + FillStyleDef *defs; + U16 i = 0; + + // Get the number of fills. + U16 nFills = GetByte(b); + + // Do we have a larger number? + if (nFills == 255) + { + // Get the larger number. + nFills = GetWord(b); + } + + *n = nFills; + defs = new FillStyleDef[ nFills ]; + if (defs == NULL) return NULL; + + // Get each of the fill style. + for (i = 0; i < nFills; i++) + { + U16 fillStyle = GetByte(b); + + defs[i].type = (FillType) fillStyle; + + if (fillStyle & 0x10) + { + defs[i].type = (FillType) (fillStyle & 0x12); + + // Get the gradient matrix. + GetMatrix(b,&(defs[i].matrix)); + + // Get the number of colors. + defs[i].gradient.nbGradients = GetByte(b); + + // Get each of the colors. + for (U16 j = 0; j < defs[i].gradient.nbGradients; j++) + { + defs[i].gradient.ratio[j] = GetByte(b); + defs[i].gradient.color[j].red = GetByte(b); + defs[i].gradient.color[j].green = GetByte(b); + defs[i].gradient.color[j].blue = GetByte(b); + if (getAlpha) { + defs[i].gradient.color[j].alpha = GetByte(b); + } else { + defs[i].gradient.color[j].alpha = ALPHA_OPAQUE; + } + } + } + else if (fillStyle & 0x40) + { + defs[i].type = (FillType) (fillStyle & 0x41); + + // Get the bitmapId + defs[i].bitmap = (Bitmap *)shape->dict->getCharacter(GetWord(b)); + // Get the bitmap matrix. + GetMatrix(b,&(defs[i].matrix)); + } + else + { + defs[i].type = (FillType) 0; + + // A solid color + defs[i].color.red = GetByte(b); + defs[i].color.green = GetByte(b); + defs[i].color.blue = GetByte(b); + if (getAlpha) { + defs[i].color.alpha = GetByte(b); + } else { + defs[i].color.alpha = ALPHA_OPAQUE; + } + } + } + + return defs; +} + +static LineStyleDef * ParseLineStyle(ShapeParser *shape, long *n, long getAlpha) +{ + BitParser *b = &shape->bit_parser; + LineStyleDef *defs,*def; + FillStyleDef *f; + long i; + + // Get the number of lines. + U16 nLines = GetByte(b); + + // Do we have a larger number? + if (nLines == 255) + { + // Get the larger number. + nLines = GetWord(b); + } + + *n = nLines; + defs = new LineStyleDef[ nLines ]; + if (defs == NULL) return NULL; + + // Get each of the line styles. + for (i = 0; i < nLines; i++) + { + def=&defs[i]; + def->width = GetWord(b); + def->color.red = GetByte(b); + def->color.green = GetByte(b); + def->color.blue = GetByte(b); + if (getAlpha) { + def->color.alpha = GetByte(b); + } else { + def->color.alpha = ALPHA_OPAQUE; + } + + f=&def->fillstyle; + f->type = f_Solid; + f->color = def->color; + if (shape->cxform) { + f->color = shape->cxform->getColor(f->color); + } + f->color.pixel = shape->gd->allocColor(f->color); + } + + return defs; +} + +/* 0 = end of shape */ +static int ParseShapeRecord(ShapeParser *shape, ShapeRecord *sr, long getAlpha) +{ + BitParser *b = &shape->bit_parser; + + // Determine if this is an edge. + BOOL isEdge = (BOOL) GetBit(b); + + if (!isEdge) + { + // Handle a state change + U16 flags = (U16) GetBits(b,5); + + // Are we at the end? + if (flags == 0) + { + // End of shape + return 0; + } + + sr->type = shapeNonEdge; + sr->flags = (ShapeFlags)flags; + + // Process a move to. + if (flags & flagsMoveTo) + { + U16 nBits = (U16) GetBits(b,5); + sr->x = GetSBits(b,nBits); + sr->y = GetSBits(b,nBits); + } + + // Get new fill info. + if (flags & flagsFill0) + { + sr->fillStyle0 = GetBits(b,shape->m_nFillBits); + } + if (flags & flagsFill1) + { + sr->fillStyle1 = GetBits(b,shape->m_nFillBits); + } + + // Get new line info + if (flags & flagsLine) + { + sr->lineStyle = GetBits(b,shape->m_nLineBits); + } + + // Check to get a new set of styles for a new shape layer. + if (flags & flagsNewStyles) + { + FillStyleDef *fillDefs; + LineStyleDef *lineDefs; + long n; + + // Parse the style. + fillDefs = ParseFillStyle(shape, &n, getAlpha); + if (fillDefs == NULL) return 0; + + sr->newFillStyles = fillDefs; + sr->nbNewFillStyles = n; + + lineDefs = ParseLineStyle(shape, &n, getAlpha); + if (lineDefs == NULL) return 0; + + sr->newLineStyles = lineDefs; + sr->nbNewLineStyles = n; + + InitBits(b); // Bug ! + + // Reset. + shape->m_nFillBits = (U16) GetBits(b,4); + shape->m_nLineBits = (U16) GetBits(b,4); + } + + //if (flags & flagsEndShape) + //printf("\tEnd of shape.\n\n"); + + return flags & flagsEndShape ? 0 : 1; + } + else + { + if (GetBit(b)) + { + sr->type = shapeLine; + + // Handle a line + U16 nBits = (U16) GetBits(b,4) + 2; // nBits is biased by 2 + + // Save the deltas + if (GetBit(b)) + { + // Handle a general line. + sr->dX = GetSBits(b,nBits); + sr->dY = GetSBits(b,nBits); + } + else + { + // Handle a vert or horiz line. + if (GetBit(b)) + { + // Vertical line + sr->dY = GetSBits(b,nBits); + sr->dX = 0; + } + else + { + // Horizontal line + sr->dX = GetSBits(b,nBits); + sr->dY = 0; + } + } + } + else + { + sr->type = shapeCurve; + + // Handle a curve + U16 nBits = (U16) GetBits(b,4) + 2; // nBits is biased by 2 + + // Get the control + sr->ctrlX = GetSBits(b,nBits); + sr->ctrlY = GetSBits(b,nBits); + + // Get the anchor + sr->anchorX = GetSBits(b,nBits); + sr->anchorY = GetSBits(b,nBits); + } + + return 1; + } +} + +static void drawShape(GraphicDevice *gd, Matrix *matrix1, Cxform *cxform, Shape *shape, + ShapeAction shapeAction, void *id,ScanLineFunc scan_line_func) +{ + LineStyleDef *l; + FillStyleDef *f0; + FillStyleDef *f1; + ShapeRecord sr1,*sr = &sr1; + int firstPoint; + long lastX,lastY; + LineStyleDef *curLineStyle; + long curNbLineStyles; + FillStyleDef *curFillStyle; + long curNbFillStyles; + StyleList *sl; + ShapeParser sp1,*sp=&sp1; + BitParser *b; + Matrix mat,*matrix; + + mat = (*gd->adjust) * (*matrix1); + matrix = &mat; + + sp->reverse = (mat.a * mat.d) < 0; + + curLineStyle = NULL; + curNbLineStyles = 0; + curFillStyle = NULL; + curNbFillStyles = 0; + sp->style_list = NULL; + + sp->shape = shape; + sp->gd = gd; + sp->matrix = matrix; + sp->cxform = cxform; + sp->dict = shape->dict; + + if (shapeAction == ShapeGetRegion) { + gd->scan_line_func = scan_line_func; + gd->scan_line_func_id = id; + } else { + gd->scan_line_func = NULL; + } + + b = &sp->bit_parser; + InitBitParser(b,shape->file_ptr); + + if (shape->getStyles) { + // ShapeWithStyle + curFillStyle = ParseFillStyle(sp, &curNbFillStyles, shape->getAlpha); + if (curFillStyle == NULL) return; + + curLineStyle = ParseLineStyle(sp, &curNbLineStyles, shape->getAlpha); + if (curLineStyle == NULL) return; + + sl = new StyleList; + if (sl == NULL) return; + + sl->next = NULL; + sl->newFillStyles = curFillStyle; + sl->nbNewFillStyles = curNbFillStyles; + sl->newLineStyles = curLineStyle; + sl->nbNewLineStyles = curNbLineStyles; + + sp->style_list = sl; + + if (shapeAction == ShapeDraw) { + prepareStyles(gd, matrix, cxform, curFillStyle, curNbFillStyles); + } + } + + InitBits(b); + sp->m_nFillBits = (U16) GetBits(b,4); + sp->m_nLineBits = (U16) GetBits(b,4); + + l = 0; + f0 = 0; + f1 = 0; + firstPoint = 1; + lastX = 0; + lastY = 0; + sp->curPath.nb_edges = 0; + sp->first_line = NULL; + sp->last_line = NULL; + + for(;;) { + if (ParseShapeRecord(sp, sr, shape->getAlpha) == 0) break; + + switch (sr->type) + { + case shapeNonEdge: + if (sr->flags & flagsNewStyles) { + + curFillStyle = sr->newFillStyles; + curNbFillStyles = sr->nbNewFillStyles; + curLineStyle = sr->newLineStyles; + curNbLineStyles = sr->nbNewLineStyles; + + sl = new StyleList; + sl->next = sp->style_list; + sl->newFillStyles = sr->newFillStyles; + sl->nbNewFillStyles = sr->nbNewFillStyles; + sl->newLineStyles = sr->newLineStyles; + sl->nbNewLineStyles = sr->nbNewLineStyles; + + sp->style_list = sl; + + if (shapeAction == ShapeDraw) { + prepareStyles(gd, matrix, cxform, curFillStyle, curNbFillStyles); + } + } + if (sr->flags & flagsFill0) { + if (sr->fillStyle0) { + if (curFillStyle) { + f0 = &curFillStyle[sr->fillStyle0-1]; + } else { + f0 = &shape->defaultFillStyle; + } + } else { + f0 = 0; + } + } + if (sr->flags & flagsFill1) { + if (sr->fillStyle1) { + if (curFillStyle) { + f1 = &curFillStyle[sr->fillStyle1-1]; + } else { + f1 = &shape->defaultFillStyle; + } + } else { + f1 = 0; + } + } + if (sr->flags & flagsLine) { + if (sr->lineStyle) { + l = &curLineStyle[sr->lineStyle-1]; + } else { + l = 0; + } + } + if (sr->flags & flagsMoveTo) { + if (sp->curPath.nb_edges == 0) { + /* if no edges, draw the polygon, then the lines */ + flushPaths(sp); + } + + newPath(sp, sr->x, sr->y); + firstPoint = 0; + + lastX = sr->x; + lastY = sr->y; + +#if PRINT + printf("---------\nX,Y = %4d,%4d\n", sr->x/20, sr->y/20); +#endif + } + break; + case shapeCurve: + // Handle Bezier Curves !!! + if (firstPoint) { + newPath(sp, 0, 0); + firstPoint = 0; + } + { + long newX,newY,ctrlX,ctrlY; + + ctrlX = lastX+sr->ctrlX; + ctrlY = lastY+sr->ctrlY; + newX = ctrlX+sr->anchorX; + newY = ctrlY+sr->anchorY; + +#if 1 + addBezier(sp, ctrlX, ctrlY, newX, newY, f0 , f1, l); +#else + addLine(sp, newX, newY, f0, f1, l); +#endif + + lastX = newX; + lastY = newY; + } + break; + case shapeLine: + if (firstPoint) { + newPath(sp, 0, 0); + firstPoint = 0; + } + + lastX += sr->dX; + lastY += sr->dY; + + addLine(sp, lastX, lastY, f0, f1, l); +#if PRINT + printf(" X, Y = %4d,%4d\n", lastX/20, lastY/20); +#endif + break; + } + } + + /* XXX: should test if there is something to draw */ + flushPaths(sp); + + /* free the styles */ + while (sp->style_list) { + StyleList *sl; + + sl=sp->style_list; + sp->style_list = sl->next; + + if (shapeAction == ShapeDraw) { + clearStyles(gd, sl->newFillStyles, sl->nbNewFillStyles); + } + + delete[] sl->newFillStyles; + delete[] sl->newLineStyles; + + delete sl; + } +} + +static void +prepareStyles(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, + FillStyleDef *ftab, long n) +{ + long fs; + FillStyleDef *f; + + for(fs = 0; fs < n; fs++) + { + f = ftab + fs; + switch (f->type) + { + case f_None: + break; + case f_Solid: + if (cxform) { + f->color = cxform->getColor(f->color); + } + f->color.pixel = gd->allocColor(f->color); + break; + case f_LinearGradient: + case f_RadialGradient: + { + Matrix mat; + int n,r,l; + long red, green, blue, alpha; + long dRed, dGreen, dBlue, dAlpha; + long min,max; + Matrix *m; + + mat = *(matrix) * f->matrix; + // Compute inverted matrix + f->gradient.imat = mat.invert(); + + /* renormalize the matrix */ + m=&f->gradient.imat; + if (f->type == f_LinearGradient) { + m->a = m->a * FRAC * (1/128.0) * 65536.0; + m->b = m->b * FRAC * (1/128.0) * 65536.0; + m->tx = (long) ((m->tx + 16384) * (1/128.0) * 65536.0); + } else { + m->a = m->a * FRAC * (1/64.0) * 65536.0; + m->b = m->b * FRAC * (1/64.0) * 65536.0; + m->c = m->c * FRAC * (1/64.0) * 65536.0; + m->d = m->d * FRAC * (1/64.0) * 65536.0; + m->tx = (long) (m->tx * (1/64.0) * 65536.0); + m->ty = (long) (m->ty * (1/64.0) * 65536.0); + } + + // Reset translation in inverted matrix + f->gradient.has_alpha = 0; + + // Build a 256 color ramp + f->gradient.ramp = new Color[256]; + if (f->gradient.ramp == NULL) { + // Invalidate fill style + f->type = f_None; + continue; + } + + // Store min and max + min = f->gradient.ratio[0]; + max = f->gradient.ratio[f->gradient.nbGradients-1]; + for(r=0; r < f->gradient.nbGradients-1; r++) + { + Color start,end; + + l = f->gradient.ratio[r+1]-f->gradient.ratio[r]; + if (l == 0) continue; + + if (cxform) { + start = cxform->getColor(f->gradient.color[r]); + end = cxform->getColor(f->gradient.color[r+1]); + } else { + start = f->gradient.color[r]; + end = f->gradient.color[r+1]; + } + + if (start.alpha != ALPHA_OPAQUE || + end.alpha != ALPHA_OPAQUE) { + f->gradient.has_alpha = 1; + } + + dRed = end.red - start.red; + dGreen = end.green - start.green; + dBlue = end.blue - start.blue; + dAlpha = end.alpha - start.alpha; + + dRed = (dRed<<16)/l; + dGreen = (dGreen<<16)/l; + dBlue = (dBlue<<16)/l; + dAlpha = (dAlpha<<16)/l; + + red = start.red <<16; + green = start.green <<16; + blue = start.blue <<16; + alpha = start.alpha <<16; + + for (n=f->gradient.ratio[r]; n<=f->gradient.ratio[r+1]; n++) { + f->gradient.ramp[n].red = red>>16; + f->gradient.ramp[n].green = green>>16; + f->gradient.ramp[n].blue = blue>>16; + f->gradient.ramp[n].alpha = alpha>>16; + + f->gradient.ramp[n].pixel = gd->allocColor(f->gradient.ramp[n]); + red += dRed; + green += dGreen; + blue += dBlue; + alpha += dAlpha; + } + } + for(n=0; ngradient.ramp[n] = f->gradient.ramp[min]; + } + for(n=max; n<256; n++) { + f->gradient.ramp[n] = f->gradient.ramp[max]; + } + } + break; + case f_TiledBitmap: + case f_clippedBitmap: + if (f->bitmap) { + Matrix *m; + + f->cmap = gd->getColormap(f->bitmap->colormap, + f->bitmap->nbColors, cxform); + if (f->cmap == NULL) { + /* Get the normal cmap anyway */ + f->cmap = f->bitmap->colormap; + } + + f->bitmap_matrix = *(matrix) * f->matrix; + + f->bitmap_matrix = f->bitmap_matrix.invert(); + + m=&f->bitmap_matrix; + m->a = m->a * FRAC * 65536.0; + m->b = m->b * FRAC * 65536.0; + m->c = m->c * FRAC * 65536.0; + m->d = m->d * FRAC * 65536.0; + m->tx = (long) (m->tx * 65536.0); + m->ty = (long) (m->ty * 65536.0); + + f->alpha_table = NULL; + + if (f->bitmap->alpha_buf && cxform) { + unsigned char *alpha_table; + int i; + + alpha_table = (unsigned char *)malloc (256); + if (alpha_table != NULL) { + for(i=0;i<256;i++) { + alpha_table[i] = cxform->getAlpha(i); + } + } + f->alpha_table = alpha_table; + } + } + break; + } + } +} + +static void +clearStyles(GraphicDevice *gd, FillStyleDef *ftab, long n) +{ + long fs; + FillStyleDef *f; + + for(fs = 0; fs < n; fs++) + { + f = ftab + fs; + switch (f->type) + { + case f_Solid: + break; + case f_LinearGradient: + case f_RadialGradient: + if (f->gradient.ramp) { + delete f->gradient.ramp; + } + break; + case f_TiledBitmap: + case f_clippedBitmap: + if (f->bitmap) { + if (f->cmap && f->cmap != f->bitmap->colormap) delete f->cmap; + if (f->alpha_table) free(f->alpha_table); + } + break; + case f_None: + break; + } + } +} + diff --git a/core/multimedia/opieplayer/libflash/shape.h b/core/multimedia/opieplayer/libflash/shape.h new file mode 100644 index 0000000..120ec94 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/shape.h @@ -0,0 +1,181 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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 _SHAPE_H_ +#define _SHAPE_H_ + +struct LineStyleDef { + long width; + Color color; + FillStyleDef fillstyle; +}; + +enum ShapeRecordType { + shapeNonEdge, + shapeCurve, + shapeLine +}; + +enum ShapeFlags { + flagsMoveTo = 0x01, + flagsFill0 = 0x02, + flagsFill1 = 0x04, + flagsLine = 0x08, + flagsNewStyles = 0x10, + flagsEndShape = 0x80 +}; + +struct ShapeRecord { + ShapeRecordType type; + + // Non Edge + ShapeFlags flags; + long x,y; // Moveto + long fillStyle0; + long fillStyle1; + long lineStyle; + FillStyleDef *newFillStyles; // Array + long nbNewFillStyles; + LineStyleDef *newLineStyles; // Array + long nbNewLineStyles; + + // Curve Edge + long ctrlX, ctrlY; + long anchorX, anchorY; + + // Straight Line + long dX,dY; + + struct ShapeRecord *next; + + ShapeRecord() { + shaperecord_size += sizeof(ShapeRecord); + shaperecord_nb++; + } + +}; + +enum ShapeAction { + ShapeDraw, + ShapeGetRegion +}; + +struct LineSegment { + long x1,y1,x2,y2; + char first; + LineStyleDef *l; + struct LineSegment *next; +}; + +struct Path { + long lastX,lastY; + int nb_edges; + int nb_segments; +}; + +struct StyleList { + FillStyleDef *newFillStyles; // Array + long nbNewFillStyles; + LineStyleDef *newLineStyles; // Array + long nbNewLineStyles; + + StyleList *next; +}; + + +/* fast bit parser */ +struct BitParser { + // Bit Handling + S32 m_bitPos; + U32 m_bitBuf; + + U8 *ptr; +}; + +class Shape; + +/* state of the shape parser */ +struct ShapeParser { + Dict *dict; /* XXX: should be put elsewhere */ + + BitParser bit_parser; + S32 m_nFillBits; + S32 m_nLineBits; + + StyleList *style_list; + Matrix *matrix; + Path curPath; + int reverse; + + /* line rasteriser */ + LineSegment *first_line,*last_line; + GraphicDevice *gd; + Cxform *cxform; + Shape *shape; + + FillStyleDef *f0; + FillStyleDef *f1; + LineStyleDef *l; +}; + +class Shape : public Character { + public: + int defLevel; // 1,2 or 3 + + + Rect boundary; + FillStyleDef defaultFillStyle; + LineStyleDef defaultLineStyle; + + Matrix lastMat; + /* parsing for the rendering stage (saves a lot of memory & + may not reduce significantly the size). These variables + should be in another structure (no state need to be + maintained between two renderings) */ + int getAlpha, getStyles; + unsigned char *file_ptr; + Dict *dict; /* XXX: should be put elsewhere */ + +protected: + void drawLines(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, long, long); + void buildSegmentList(Segment **segs, int height, long &n, Matrix *matrix, int update, int reverse); + Segment *progressSegments(Segment *, long); + Segment *newSegments(Segment *, Segment *); + +public: + Shape(long id = 0 , int level = 1); + ~Shape(); + + void setBoundingBox(Rect rect); + int execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform); + void getRegion(GraphicDevice *gd, Matrix *matrix, + void *id, ScanLineFunc scan_line_func); + + void getBoundingBox(Rect *bb, DisplayListEntry *); + +#ifdef DUMP + void dump(BitStream *bs); + void dumpShapeRecords(BitStream *bs, int alpha); + void dumpFillStyles(BitStream *bs, FillStyleDef *defs, long n, int alpha); + void dumpLineStyles(BitStream *bs, LineStyleDef *defs, long n, int alpha); + void checkBitmaps(BitStream *bs); +#endif +}; + +#endif /* _SHAPE_H_ */ diff --git a/core/multimedia/opieplayer/libflash/sound.cc b/core/multimedia/opieplayer/libflash/sound.cc new file mode 100644 index 0000000..e93f9b5 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/sound.cc @@ -0,0 +1,439 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#include +#include +#include +#ifndef NOSOUND +#include +#endif + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +#define PRINT 0 + +//////////// SOUND + +Sound::Sound(long id) : Character(SoundType, id) +{ + samples = 0; + stereo = 0; + soundRate = 0; + sampleSize = 1; +} + +Sound::~Sound() +{ + if (samples) { + delete samples; + } +} + +void +Sound::setSoundFlags(long f) { + switch (GET_SOUND_RATE_CODE(f)) { + case 0: + soundRate = 5500; + break; + case 1: + soundRate = 11000; + break; + case 2: + soundRate = 22000; + break; + case 3: + soundRate = 44000; + break; + } + if (f & soundIs16bit) { + sampleSize = 2; + } + if (f & soundIsStereo) { + stereo = 1; + } + +#if PRINT + printf("-----\nFlags = %2x\n", f); + printf("Rate = %d kHz ", soundRate); + printf("SampleSize = %d byte(s) ", sampleSize); + if (f & soundIsStereo) { + printf("Stereo "); + } else { + printf("Mono "); + } + if (f & soundIsADPCMCompressed) { + printf("ADPCM\n"); + } else { + printf("Raw\n"); + } +#endif +} + +char * +Sound::setNbSamples(long n) { + long size; + + nbSamples = n; + + size = nbSamples * (stereo ? 2 : 1) * sampleSize; + + samples = new char[ size ]; + + memset((char *)samples,0, size); + + return samples; +} + +long +Sound::getRate() { + return soundRate; +} + +long +Sound::getChannel() { + return stereo ? 2 : 1; +} + +long +Sound::getNbSamples() { + return nbSamples; +} + +long +Sound::getSampleSize() { + return sampleSize; +} + +char * +Sound::getSamples() { + return samples; +} + +//////////// SOUND MIXER + +long SoundMixer::dsp = -1; // Init of descriptor +long SoundMixer::blockSize = 0; // Driver sound buffer size +long SoundMixer::nbInst = 0; // Nb SoundMixer instances +long SoundMixer::sampleSize = 0; +long SoundMixer::stereo = 0; +long SoundMixer::soundRate = 0; +char *SoundMixer::buffer = 0; + +SoundMixer::SoundMixer(char *device) +{ +#ifndef NOSOUND + int status; + long fmt; + + list = 0; // No sound to play + + if (nbInst++) { + // Device is already open + return; + } + + dsp = open(device,O_WRONLY); + if (dsp < 0) { + perror("open dsp"); + return; + } + + // Reset device + status = ioctl(dsp, SNDCTL_DSP_RESET); + if (status < 0) perror("ioctl SNDCTL_DSP_RESET"); + + // Set sample size + fmt = AFMT_S16_LE; + sampleSize = 2; + status = ioctl(dsp, SNDCTL_DSP_SETFMT, &fmt); + if (status < 0) perror("ioctl SNDCTL_DSP_SETFMT"); + + if (status) { + fmt = AFMT_U8; + sampleSize = 1; + status = ioctl(dsp, SNDCTL_DSP_SETFMT, &fmt); + if (status < 0) perror("ioctl SNDCTL_DSP_SETFMT"); + } + + // Set stereo channel + stereo = 1; + status = ioctl(dsp, SNDCTL_DSP_STEREO, &stereo); + + if (status) { + stereo = 0; + } + + // Set sound rate in Hertz + soundRate = 11000; + status = ioctl(dsp, SNDCTL_DSP_SPEED, &soundRate); + if (status < 0) perror("ioctl SNDCTL_DSP_SPEED"); + + // Get device buffer size + status = ioctl(dsp, SNDCTL_DSP_GETBLKSIZE, &blockSize); + if (status < 0) perror("ioctl SNDCTL_DSP_GETBLKSIZE"); + if (blockSize < 1024) { + blockSize = 32768; + } + blockSize *= 2; + + buffer = (char *)malloc(blockSize); + if (buffer == 0) { + close(dsp); + dsp = -1; + } + +#if PRINT + int caps; + + ioctl(dsp,SNDCTL_DSP_GETCAPS, &caps); + printf("Audio capabilities = %x\n", caps); + printf("Sound Rate = %d\n", soundRate); + printf("Stereo = %d\n", stereo); + printf("Sample Size = %d\n", sampleSize); + printf("Buffer Size = %d\n", blockSize); +#endif /* PRINT */ + +#endif /* NOSOUND */ +} + +SoundMixer::~SoundMixer() +{ + if (--nbInst == 0) { + if (dsp > 0) { + close(dsp); + free(buffer); + } + } +} + +void +SoundMixer::stopSounds() +{ +#ifndef NOSOUND + SoundList *sl,*del; + + for(sl = list; sl; ) { + del = sl; + sl = sl->next; + delete del; + } + list = 0; +#endif +} + +void +SoundMixer::startSound(Sound *sound) +{ +#ifndef NOSOUND + SoundList *sl; + + if (sound) { + // Add sound in list + sl = new SoundList; + sl->rate = sound->getRate(); + sl->stereo = (sound->getChannel() == 2); + sl->sampleSize = sound->getSampleSize(); + sl->current = sound->getSamples(); + sl->remaining = sound->getSampleSize()*sound->getNbSamples()*sound->getChannel(); + sl->next = list; + list = sl; + } +#endif +} + +long +SoundMixer::playSounds() +{ +#ifndef NOSOUND + audio_buf_info bufInfo; + long nbBytes, n; + SoundList *sl,*prev; + int status; + + // Init failed + if (dsp < 0) return 0; + + // No sound to play + if (list == 0) return 0; + + // Get free DMA buffer space + status = ioctl(dsp, SNDCTL_DSP_GETOSPACE, &bufInfo); + + // Free space is not large enough to output data without blocking + // But there are still sounds to play. We must wait. + if (bufInfo.bytes < blockSize) return 1; + + nbBytes = 0; + + // Fill buffer with silence. + memset((void*)buffer, 0, blockSize); + + prev = 0; + sl = list; + while(sl) { + + // Ask sound to fill the buffer + // according to device capabilities + n = fillSoundBuffer(sl, buffer, blockSize); + + // Remember the largest written size + if (n > nbBytes) { + nbBytes = n; + } + + // No more samples for this sound + if (sl->remaining == 0) { + // Remove sound from list + if (prev) { + prev->next = sl->next; + delete sl; + sl = prev->next; + } else { + list = sl->next; + delete sl; + sl = list; + } + } else { + sl = sl->next; + } + } + + if (nbBytes) { + // At last ! Play It ! + write(dsp,buffer,nbBytes); + status = ioctl(dsp, SNDCTL_DSP_POST); + } + + return nbBytes; +#else + return 0; +#endif +} + +long +SoundMixer::fillSoundBuffer(SoundList *sl, char *buff, long buffSize) +{ + long sampleLeft, sampleRight; + long skipOut, skipOutInit; + long skipIn, skipInInit; + long freqRatio; + long totalOut = 0; + + sampleLeft = sampleRight = 0; + skipOutInit = skipInInit = 0; + + freqRatio = sl->rate / soundRate; + if (freqRatio) { + skipOutInit = freqRatio - 1; + skipInInit = 0; + } + + freqRatio = soundRate / sl->rate; + if (freqRatio) { + skipInInit = freqRatio - 1; + skipOutInit = 0; + } + + skipOut = skipOutInit; + skipIn = skipInInit; + while (buffSize && sl->remaining) { + if (skipIn-- == 0) { + // Get sampleLeft + if (sl->sampleSize == 2) { + sampleLeft = (long)(*(short *)(sl->current)); + if (sampleSize == 1) { + sampleLeft = (sampleLeft >> 8) &0xff; + } + } else { + sampleLeft = (long)*(sl->current); + if (sampleSize == 2) { + sampleLeft <<= 8; + } + } + sl->current += sl->sampleSize; + sl->remaining -= sl->sampleSize; + + if (sl->stereo) { + // Get sampleRight + if (sl->sampleSize == 2) { + sampleRight = (long)(*(short *)(sl->current)); + if (sampleSize == 1) { + sampleRight = (sampleRight >> 8) &0xff; + } + } else { + sampleRight = (long)*(sl->current); + if (sampleSize == 2) { + sampleRight <<= 8; + } + } + sl->current += sl->sampleSize; + sl->remaining -= sl->sampleSize; + + } else { + sampleRight = sampleLeft; + } + + skipIn = skipInInit; + } + + if (skipOut-- == 0) { + // Output + if (stereo) { + if (sampleSize == 2) { + *((short *)buff) += sampleLeft/2; + buffSize -= sampleSize; + buff += sampleSize; + *((short *)buff) += sampleRight/2; + buffSize -= sampleSize; + buff += sampleSize; + } else { + *((char *)buff) += sampleLeft/2; + buffSize -= sampleSize; + buff += sampleSize; + *((char *)buff) += sampleRight/2; + buffSize -= sampleSize; + buff += sampleSize; + } + totalOut += 2*sampleSize; + } else { + if (sampleSize == 2) { + *((short *)buff) += (sampleLeft+sampleRight)>>2; + buffSize -= sampleSize; + buff += sampleSize; + } else { + *((char *)buff) += (sampleLeft+sampleRight)>>2; + buffSize -= sampleSize; + buff += sampleSize; + } + totalOut += sampleSize; + } + + skipOut = skipOutInit; + } + } + + return totalOut; +} diff --git a/core/multimedia/opieplayer/libflash/sound.h b/core/multimedia/opieplayer/libflash/sound.h new file mode 100644 index 0000000..c53773d --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/sound.h @@ -0,0 +1,83 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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 _SOUND_H_ +#define _SOUND_H_ + +#define GET_SOUND_RATE_CODE(f) (((f)&0x0c)>>2) + +class Sound : public Character { + long soundRate; // In hz + long stereo; // True if stereo sound + long sampleSize; // 1 or 2 bytes + + char *samples; // Array of samples + long nbSamples; + +public: + Sound(long id); + ~Sound(); + void setSoundFlags(long f); + char *setNbSamples(long n); + + long getRate(); + long getChannel(); + long getNbSamples(); + long getSampleSize(); + char *getSamples(); +}; + +struct SoundList { + long rate; + long stereo; + long sampleSize; + long nbSamples; + long remaining; + char *current; + + SoundList *next; +}; + +class SoundMixer { + + SoundList *list; + +// Class variables +static long dsp; // Descriptor for /dev/dsp +static char * buffer; // DMA buffer +static long blockSize; +static long nbInst; // Number of instances + + // Sound Device Capabilities +static long soundRate; // In hz +static long stereo; // True if stereo sound +static long sampleSize; // 1 or 2 bytes + +public: + SoundMixer(char*); + ~SoundMixer(); + + void startSound(Sound *sound); // Register a sound to be played + void stopSounds(); // Stop every current sounds in the instance + + long playSounds(); // Actually play sounds of all instances + long fillSoundBuffer(SoundList *, char *buffer, long bufferSize); // Fill sound buffer +}; + +#endif /* _SOUND_H_ */ diff --git a/core/multimedia/opieplayer/libflash/sprite.cc b/core/multimedia/opieplayer/libflash/sprite.cc new file mode 100644 index 0000000..de53095 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/sprite.cc @@ -0,0 +1,91 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +Sprite::Sprite(FlashMovie *movie, long id, long frameCount) : Character(SpriteType, id) +{ + program = new Program(movie, frameCount); + if (program == NULL) return; + if (program->totalFrames == 0) { + delete program; + program = NULL; + return; + } + program->dl->isSprite = 1; +} + +Sprite::~Sprite() +{ + delete program; +} + +void +Sprite::reset() +{ + program->rewindMovie(); +} + +int +Sprite::isSprite(void) +{ + return 1; +} + +Program * +Sprite::getProgram() +{ + return program; +} + +int +Sprite::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform) +{ + return program->dl->render(gd,matrix,cxform); +} + +ActionRecord * +Sprite::eventHandler(GraphicDevice *gd, FlashEvent *event) +{ +#if 0 + DisplayList *dl; + ActionRecord *actions; + + dl = program->getDisplayList(); + actions = dl->processEvent(gd, event); + if (actions) { + program->doAction(actions,0); + } + return actions; +#endif + return NULL; +} + +void +Sprite::getBoundingBox(Rect *bb, DisplayListEntry *e) +{ + program->dl->getBoundary(bb); +} diff --git a/core/multimedia/opieplayer/libflash/sprite.h b/core/multimedia/opieplayer/libflash/sprite.h new file mode 100644 index 0000000..2ea64bc --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/sprite.h @@ -0,0 +1,38 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998 Olivier Debon +// +// 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 _SPRITE_H_ +#define _SPRITE_H_ + +class Sprite : public Character { +public: + Program *program; + + Sprite(FlashMovie *movie, long id, long frameCount); + ~Sprite(); + Program *getProgram(); + int execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform); + int hasEventHandler(); + void reset(); + ActionRecord *eventHandler(GraphicDevice *, FlashEvent *); + int isSprite(void); + void getBoundingBox(Rect *bb, DisplayListEntry *de); +}; + +#endif /* _SPRITE_H_ */ diff --git a/core/multimedia/opieplayer/libflash/sqrt.cc b/core/multimedia/opieplayer/libflash/sqrt.cc new file mode 100644 index 0000000..0d8295e --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/sqrt.cc @@ -0,0 +1,4099 @@ +unsigned char SQRT[] = { + +0,1,1,1,2,2,2,2,2,3,3,3,3,3,3,3, +4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5, +5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6, +6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, +9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10, +10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, +12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13, +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, +13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14, +14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, +14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, +15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, +17,17,17,17,18,18,18,18,18,18,18,18,18,18,18,18, +18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, +18,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21, +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, +21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22, +22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, +22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, +22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24, +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24, +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24, +24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, +25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26, +26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, +26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, +26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27, +27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27, +27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27, +27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27, +28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, +28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, +28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, +28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29, +29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29, +29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29, +29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29, +29,29,29,29,30,30,30,30,30,30,30,30,30,30,30,30, +30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, +30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, +30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, +30,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, +31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, +31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, +31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33, +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33, +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33, +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33, +33,33,33,33,34,34,34,34,34,34,34,34,34,34,34,34, +34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34, +34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34, +34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34, +34,34,34,34,34,34,34,34,34,35,35,35,35,35,35,35, +35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35, +35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35, +35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35, +35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35, +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, +36,36,36,36,36,36,36,36,36,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,38,38,38,38,38,38,38,38,38,38,38,38, +38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, +38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, +38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, +38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, +38,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39, +39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39, +39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39, +39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39, +39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39, +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40, +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40, +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40, +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40, +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40, +40,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41, +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41, +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41, +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41, +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41, +41,41,41,41,42,42,42,42,42,42,42,42,42,42,42,42, +42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42, +42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42, +42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42, +42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42, +42,42,42,42,42,42,42,42,42,43,43,43,43,43,43,43, +43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, +43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, +43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, +43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, +43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, +44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, +44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, +44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, +44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, +44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, +44,44,44,44,44,44,44,44,44,45,45,45,45,45,45,45, +45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, +45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, +45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, +45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, +45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, +45,45,45,45,46,46,46,46,46,46,46,46,46,46,46,46, +46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46, +46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46, +46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46, +46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46, +46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46, +46,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, +47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, +47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, +47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, +47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, +47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48, +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48, +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48, +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48, +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48, +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48, +48,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, +49,49,49,49,50,50,50,50,50,50,50,50,50,50,50,50, +50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50, +50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50, +50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50, +50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50, +50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50, +50,50,50,50,50,50,50,50,50,51,51,51,51,51,51,51, +51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51, +51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51, +51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51, +51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51, +51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51, +51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51, +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52, +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52, +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52, +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52, +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52, +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52, +52,52,52,52,52,52,52,52,52,53,53,53,53,53,53,53, +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53, +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53, +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53, +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53, +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53, +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53, +53,53,53,53,54,54,54,54,54,54,54,54,54,54,54,54, +54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, +54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, +54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, +54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, +54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, +54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, +54,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55, +55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55, +55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55, +55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55, +55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55, +55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55, +55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55, +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56, +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56, +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56, +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56, +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56, +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56, +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56, +56,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, +57,57,57,57,58,58,58,58,58,58,58,58,58,58,58,58, +58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58, +58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58, +58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58, +58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58, +58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58, +58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58, +58,58,58,58,58,58,58,58,58,59,59,59,59,59,59,59, +59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, +59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, +59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, +59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, +59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, +59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, +59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, +60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, +60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, +60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, +60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, +60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, +60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, +60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, +60,60,60,60,60,60,60,60,60,61,61,61,61,61,61,61, +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, +61,61,61,61,62,62,62,62,62,62,62,62,62,62,62,62, +62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, +62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, +62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, +62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, +62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, +62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, +62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, +62,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, +63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, +63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, +63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, +63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, +63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, +63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, +63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65, +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65, +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65, +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65, +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65, +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65, +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65, +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65, +65,65,65,65,66,66,66,66,66,66,66,66,66,66,66,66, +66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, +66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, +66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, +66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, +66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, +66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, +66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, +66,66,66,66,66,66,66,66,66,67,67,67,67,67,67,67, +67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, +68,68,68,68,68,68,68,68,68,69,69,69,69,69,69,69, +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, +69,69,69,69,70,70,70,70,70,70,70,70,70,70,70,70, +70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70, +70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70, +70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70, +70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70, +70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70, +70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70, +70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70, +70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70, +70,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71, +71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71, +71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71, +71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71, +71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71, +71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71, +71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71, +71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71, +71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71, +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72, +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72, +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72, +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72, +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72, +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72, +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72, +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72, +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72, +72,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73, +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73, +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73, +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73, +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73, +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73, +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73, +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73, +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73, +73,73,73,73,74,74,74,74,74,74,74,74,74,74,74,74, +74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74, +74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74, +74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74, +74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74, +74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74, +74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74, +74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74, +74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74, +74,74,74,74,74,74,74,74,74,75,75,75,75,75,75,75, +75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75, +75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75, +75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75, +75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75, +75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75, +75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75, +75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75, +75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75, +75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75, +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +76,76,76,76,76,76,76,76,76,77,77,77,77,77,77,77, +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, +77,77,77,77,78,78,78,78,78,78,78,78,78,78,78,78, +78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78, +78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78, +78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78, +78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78, +78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78, +78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78, +78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78, +78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78, +78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78, +78,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, +79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, +79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, +79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, +79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, +79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, +79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, +79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, +79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, +79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79, +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, +80,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81, +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81, +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81, +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81, +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81, +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81, +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81, +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81, +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81, +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81, +81,81,81,81,82,82,82,82,82,82,82,82,82,82,82,82, +82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, +82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, +82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, +82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, +82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, +82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, +82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, +82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, +82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, +82,82,82,82,82,82,82,82,82,83,83,83,83,83,83,83, +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83, +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84, +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84, +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84, +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84, +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84, +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84, +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84, +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84, +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84, +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84, +84,84,84,84,84,84,84,84,84,85,85,85,85,85,85,85, +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85, +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85, +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85, +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85, +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85, +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85, +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85, +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85, +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85, +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85, +85,85,85,85,86,86,86,86,86,86,86,86,86,86,86,86, +86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86, +86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86, +86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86, +86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86, +86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86, +86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86, +86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86, +86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86, +86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86, +86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86, +86,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87, +87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87, +87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87, +87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87, +87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87, +87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87, +87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87, +87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87, +87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87, +87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87, +87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87, +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88, +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88, +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88, +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88, +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88, +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88, +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88, +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88, +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88, +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88, +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88, +88,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89, +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89, +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89, +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89, +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89, +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89, +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89, +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89, +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89, +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89, +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89, +89,89,89,89,90,90,90,90,90,90,90,90,90,90,90,90, +90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90, +90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90, +90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90, +90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90, +90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90, +90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90, +90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90, +90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90, +90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90, +90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90, +90,90,90,90,90,90,90,90,90,91,91,91,91,91,91,91, +91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, +91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, +91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, +91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, +91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, +91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, +91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, +91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, +91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, +91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, +91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,93,93,93,93,93,93,93, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, +93,93,93,93,94,94,94,94,94,94,94,94,94,94,94,94, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, +94,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96, +96,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, +97,97,97,97,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, +98,98,98,98,98,98,98,98,98,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,100,100,100,100,100,100,100,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, +101,101,101,101,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, +104,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +105,105,105,105,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, +106,106,106,106,106,106,106,106,106,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, +108,108,108,108,108,108,108,108,108,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, +109,109,109,109,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, +110,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, +112,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, +114,114,114,114,114,114,114,114,114,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, +116,116,116,116,116,116,116,116,116,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117, +117,117,117,117,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, +118,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +121,121,121,121,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +126,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, +129,129,129,129,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, +133,133,133,133,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, +136,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, +142,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, +144,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, +145,145,145,145,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, +146,146,146,146,146,146,146,146,146,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, +148,148,148,148,148,148,148,148,148,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, +149,149,149,149,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, +152,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, +161,161,161,161,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, +162,162,162,162,162,162,162,162,162,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, +164,164,164,164,164,164,164,164,164,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, +166,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, +168,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, +170,170,170,170,170,170,170,170,170,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,172,172,172,172,172,172,172,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, +173,173,173,173,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, +176,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +177,177,177,177,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +178,178,178,178,178,178,178,178,178,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, +180,180,180,180,180,180,180,180,180,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, +182,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, +184,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, +188,188,188,188,188,188,188,188,188,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, +189,189,189,189,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, +193,193,193,193,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, +194,194,194,194,194,194,194,194,194,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, +197,197,197,197,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, +198,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +200,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, +202,202,202,202,202,202,202,202,202,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, +205,205,205,205,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, +206,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, +208,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, +209,209,209,209,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, +210,210,210,210,210,210,210,210,210,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, +212,212,212,212,212,212,212,212,212,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, +218,218,218,218,218,218,218,218,218,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +225,225,225,225,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, +228,228,228,228,228,228,228,228,228,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, +230,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +234,234,234,234,234,234,234,234,234,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, +236,236,236,236,236,236,236,236,236,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,237,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, +241,241,241,241,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242, +242,242,242,242,242,242,242,242,242,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, +246,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, +249,249,249,249,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 +}; diff --git a/core/multimedia/opieplayer/libflash/swf.h b/core/multimedia/opieplayer/libflash/swf.h new file mode 100644 index 0000000..5f5e4f7 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/swf.h @@ -0,0 +1,229 @@ +#ifndef _SWF_H_ +#define _SWF_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef DUMP +#include "bitstream.h" +#endif + +#include "flash.h" + +extern int debug; + +// Global Types +typedef unsigned long U32, *P_U32, **PP_U32; +typedef signed long S32, *P_S32, **PP_S32; +typedef unsigned short U16, *P_U16, **PP_U16; +typedef signed short S16, *P_S16, **PP_S16; +typedef unsigned char U8, *P_U8, **PP_U8; +typedef signed char S8, *P_S8, **PP_S8; +typedef signed long SFIXED, *P_SFIXED; +typedef signed long SCOORD, *P_SCOORD; +typedef unsigned long BOOL; + +#define ZOOM(v,f) ((v)/(f)) + +#include "matrix.h" +#include "cxform.h" +#include "rect.h" + +#include +#define ST struct timeval t1,t2; +#define START gettimeofday(&t1,0) +#define STOP(msg) gettimeofday(&t2,0); printf("%s Delta = %d ms\n", msg, (t2.tv_sec-t1.tv_sec)*1000+(t2.tv_usec-t1.tv_usec)/1000); fflush(stdout); + +// Start Sound Flags +enum { + soundHasInPoint = 0x01, + soundHasOutPoint = 0x02, + soundHasLoops = 0x04, + soundHasEnvelope = 0x08 + + // the upper 4 bits are reserved for synchronization flags +}; + +// Flags for Sound Format +enum SounfFlags { + soundIsStereo = 0x01, + soundIs16bit = 0x02, + soundIsADPCMCompressed = 0x10 +}; + +// Flags for defining Button States +enum ButtonState { + stateHitTest = 0x08, + stateDown = 0x04, + stateOver = 0x02, + stateUp = 0x01 +}; + +// Actions +enum Action { + // Internal actions + ActionRefresh = 0x00, + ActionPlaySound = 0x01, + // Normal actions + ActionGotoFrame = 0x81, + ActionGetURL = 0x83, + ActionNextFrame = 0x04, + ActionPrevFrame = 0x05, + ActionPlay = 0x06, + ActionStop = 0x07, + ActionToggleQuality = 0x08, + ActionStopSounds = 0x09, + ActionWaitForFrame = 0x8a, + ActionSetTarget = 0x8b, + ActionGoToLabel = 0x8c +}; + +class Sound; + +struct ActionRecord { + Action action; + + // GotoFrame & WaitForFrame + long frameIndex; + + // GetURL + char *url; + char *target; + + // GotoLabel + char *frameLabel; + + // WaitForFrame + long skipCount; + + // Sound + Sound *sound; + + struct ActionRecord *next; + + ActionRecord() { + frameLabel = 0; + url = 0; + target = 0; + sound = 0; + }; + + ~ActionRecord() { + if (frameLabel) free(frameLabel); + if (url) free(url); + if (target) free(target); + }; +}; + +enum FontFlags { + fontUnicode = 0x20, + fontShiftJIS = 0x10, + fontANSI = 0x08, + fontItalic = 0x04, + fontBold = 0x02, + fontWideCodes = 0x01 +}; + +enum TextFlags { + isTextControl = 0x80, + + textIsLarge = 0x70, + textHasFont = 0x08, + textHasColor = 0x04, + textHasYOffset= 0x02, + textHasXOffset= 0x01 +}; + +#ifndef NULL +#define NULL 0 +#endif + +// Tag values that represent actions or data in a Flash script. +enum +{ + stagEnd = 0, + stagShowFrame = 1, + stagDefineShape = 2, + stagFreeCharacter = 3, + stagPlaceObject = 4, + stagRemoveObject = 5, + stagDefineBits = 6, + stagDefineButton = 7, + stagJPEGTables = 8, + stagSetBackgroundColor = 9, + stagDefineFont = 10, + stagDefineText = 11, + stagDoAction = 12, + stagDefineFontInfo = 13, + stagDefineSound = 14, // Event sound tags. + stagStartSound = 15, + stagStopSound = 16, + stagDefineButtonSound = 17, + stagSoundStreamHead = 18, + stagSoundStreamBlock = 19, + stagDefineBitsLossless = 20, // A bitmap using lossless zlib compression. + stagDefineBitsJPEG2 = 21, // A bitmap using an internal JPEG compression table. + stagDefineShape2 = 22, + stagDefineButtonCxform = 23, + stagProtect = 24, // This file should not be importable for editing. + + // These are the new tags for Flash 3. + stagPlaceObject2 = 26, // The new style place w/ alpha color transform and name. + stagRemoveObject2 = 28, // A more compact remove object that omits the character tag (just depth). + stagDefineShape3 = 32, // A shape V3 includes alpha values. + stagDefineText2 = 33, // A text V2 includes alpha values. + stagDefineButton2 = 34, // A button V2 includes color transform, alpha and multiple actions + stagDefineBitsJPEG3 = 35, // A JPEG bitmap with alpha info. + stagDefineBitsLossless2 = 36, // A lossless bitmap with alpha info. + stagDefineSprite = 39, // Define a sequence of tags that describe the behavior of a sprite. + stagNameCharacter = 40, // Name a character definition, character id and a string, (used for buttons, bitmaps, sprites and sounds). + stagFrameLabel = 43, // A string label for the current frame. + stagSoundStreamHead2 = 45, // For lossless streaming sound, should not have needed this... + stagDefineMorphShape = 46, // A morph shape definition + stagDefineFont2 = 48, + + notEnoughData = 0xffff, // Special code +}; + +#ifndef false +#define false 0 +#endif +#ifndef true +#define true 1 +#endif + +extern int shape_size,shape_nb,shaperecord_size,shaperecord_nb,style_size,style_nb; + +typedef void (*ScanLineFunc)(void *id, long y, long start, long end); + +class Bitmap; +struct FlashMovie; + +extern "C" { +#include "jpeglib.h" +}; +extern "C" { +//#include "zlib.h" +#include "../src/3rdparty/zlib/zlib.h" +}; + +#include "graphic.h" +#include "character.h" +#include "bitmap.h" +#include "shape.h" +#include "displaylist.h" +#include "sound.h" +#include "button.h" +#include "font.h" +#include "text.h" +#include "adpcm.h" +#include "program.h" +#include "sprite.h" +#include "script.h" +#include "movie.h" + +#endif /* _SWF_H_ */ diff --git a/core/multimedia/opieplayer/libflash/text.cc b/core/multimedia/opieplayer/libflash/text.cc new file mode 100644 index 0000000..1b6cb5e --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/text.cc @@ -0,0 +1,246 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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. +// +/////////////////////////////////////////////////////////////// +// Author : Olivier Debon +// + +#include "swf.h" + +#ifdef RCSID +static char *rcsid = "$Id$"; +#endif + +Text::Text(long id) : Character(TextType, id) +{ + textRecords = 0; +} + +Text::~Text() +{ + TextRecord *cur,*del; + + for(cur = textRecords; cur;) + { + del = cur; + cur = cur->next; + delete del; + } +} + +void +Text::setTextBoundary(Rect rect) +{ + boundary = rect; +} + +void +Text::setTextMatrix(Matrix m) +{ + textMatrix = m; +} + +void +Text::addTextRecord(TextRecord *tr) +{ + SwfFont *font = 0; + long n; + + tr->next = 0; + + if (textRecords == 0) { + textRecords = tr; + font = tr->font; + } else { + TextRecord *current; + long fontHeight = 0; + + for(current = textRecords; current->next; current = current->next) { + if (current->flags & textHasFont) { + font = current->font; + fontHeight = current->fontHeight; + } + } + + current->next = tr; + if (current->flags & textHasFont) { + font = current->font; + fontHeight = current->fontHeight; + } + + if (tr->flags & textHasFont) { + font = tr->font; + } else { + tr->font = font; + tr->fontHeight = fontHeight; + } + } + + if (tr->nbGlyphs) { + for(n=0; n < tr->nbGlyphs; n++) { + tr->glyphs[n].code = font->getGlyphCode(tr->glyphs[n].index); + } + } +} + +int +Text::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform) +{ + return doText(gd, matrix, cxform, ShapeDraw, NULL, NULL); +} + +void +Text::getRegion(GraphicDevice *gd, Matrix *matrix, + void *id, ScanLineFunc scan_line_func) +{ + doText(gd, matrix, 0, ShapeGetRegion, id, scan_line_func); +} + +void +Text::getBoundingBox(Rect *bb, DisplayListEntry *e) +{ + *bb = boundary; +} + +TextRecord * +Text::getTextRecords() +{ + return textRecords; +} + +int +Text::doText(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, ShapeAction action, + void *id, ScanLineFunc scan_line_func) +{ + TextRecord *tr; + long x,y; // Current position + SwfFont *font = 0; // Current font + long fontHeight; + Matrix tmat,fmat; + long g; + + x = y = 0; + fontHeight = 0; + + // Compute final text matrix + tmat = (*matrix) * textMatrix; + + for(tr = textRecords; tr; tr = tr ->next) + { + if (tr->flags & isTextControl) { + if (tr->flags & textHasXOffset) { + x = tr->xOffset; + } + if (tr->flags & textHasYOffset) { + y = tr->yOffset; + } + if (tr->flags & textHasColor) { + if (action == ShapeDraw) { + if (cxform) { + gd->setForegroundColor(cxform->getColor(tr->color)); + } else { + gd->setForegroundColor(tr->color); + } + } + } + } + + font = tr->font; + fontHeight = tr->fontHeight; + // Update font matrix + fmat.a = fontHeight/1000.0; + fmat.d = fontHeight/1000.0; + + assert(font != 0); + for (g = 0; g < tr->nbGlyphs; g++) + { + Shape *shape; + Matrix cmat; + + shape = font->getGlyph( tr->glyphs[g].index ); + +#ifdef PRINT + printf("%c", font->getGlyphCode(tr->glyphs[g].index)); +#endif + + // Update font matrix + fmat.tx = x; + fmat.ty = y; + + // Compute Character matrix + cmat = tmat * fmat; + + if (action == ShapeDraw) { + shape->execute(gd, &cmat, cxform); + } else { + shape->getRegion(gd, &cmat, id, scan_line_func); + } + + // Advance + x += tr->glyphs[g].xAdvance; + } +#ifdef PRINT + printf("\n"); +#endif + } + + if (gd->showMore) { + tmat = (*gd->adjust) * (*matrix); + + long x1,x2,y1,y2; + + x1 = boundary.xmin; + y1 = boundary.ymin; + x2 = boundary.xmax; + y2 = boundary.ymax; + gd->drawLine(tmat.getX(x1,y1),tmat.getY(x1,y1),tmat.getX(x2,y1),tmat.getY(x2,y1),FRAC); + gd->drawLine(tmat.getX(x2,y1),tmat.getY(x2,y1),tmat.getX(x2,y2),tmat.getY(x2,y2),FRAC); + gd->drawLine(tmat.getX(x2,y2),tmat.getY(x2,y2),tmat.getX(x1,y2),tmat.getY(x1,y2),FRAC); + gd->drawLine(tmat.getX(x1,y2),tmat.getY(x1,y2),tmat.getX(x1,y1),tmat.getY(x1,y1),FRAC); + } + + return 0; +} + +////////// TextRecord Methods +TextRecord::TextRecord() { + flags = (TextFlags)0; + font = 0; + fontHeight = 0; + nbGlyphs = 0; + glyphs = 0; + xOffset = 0; + yOffset = 0; +} + +TextRecord::~TextRecord() { + if (nbGlyphs) delete glyphs; +} + +char * +TextRecord::getText() { + static char text[256]; + long g; + + for(g=0; g < nbGlyphs; g++) { + text[g] = glyphs[g].code; + } + text[g] = 0; + + return text; +} diff --git a/core/multimedia/opieplayer/libflash/text.h b/core/multimedia/opieplayer/libflash/text.h new file mode 100644 index 0000000..1ba7b74 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/text.h @@ -0,0 +1,77 @@ +///////////////////////////////////////////////////////////// +// Flash Plugin and Player +// Copyright (C) 1998,1999 Olivier Debon +// +// 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 _TEXT_H_ +#define _TEXT_H_ + +struct Glyph { + long index; + long xAdvance; + long code; // Ascii code +}; + +struct TextRecord { + + // Normal text record + Glyph *glyphs; + long nbGlyphs; + + // Control text record + TextFlags flags; + SwfFont *font; + long fontHeight; + Color color; + long xOffset; + long yOffset; + + TextRecord *next; + + TextRecord(); + ~TextRecord(); + + char *getText(); +}; + +class Text : public Character { + + Rect boundary; + Matrix textMatrix; + TextRecord *textRecords; // List + +public: + Text(long id); + ~Text(); + + void setTextBoundary(Rect rect); + void setTextMatrix(Matrix m); + void addTextRecord(TextRecord *tr); + int execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform); + void getRegion(GraphicDevice *gd, Matrix *matrix, + void *id, ScanLineFunc scan_line_func); + int doText(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, ShapeAction action, + void *id, ScanLineFunc scan_line_func); + void getBoundingBox(Rect *bb, DisplayListEntry *e); + TextRecord *getTextRecords(); + +#ifdef DUMP + void dump(BitStream *bs); +#endif +}; + +#endif /* _TEXT_H_ */ diff --git a/core/multimedia/opieplayer/libmad/.cvsignore b/core/multimedia/opieplayer/libmad/.cvsignore new file mode 100644 index 0000000..6fe2396 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/.cvsignore @@ -0,0 +1,2 @@ +moc_* +Makefile diff --git a/core/multimedia/opieplayer/libmad/D.dat b/core/multimedia/opieplayer/libmad/D.dat new file mode 100644 index 0000000..f33d30c --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/D.dat @@ -0,0 +1,607 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +/* + * These are the coefficients for the subband synthesis window. This is a + * reordered version of Table B.3 from ISO/IEC 11172-3. + * + * Every value is parameterized so that shift optimizations can be made at + * compile-time. For example, every value can be right-shifted 12 bits to + * minimize multiply instruction times without any loss of accuracy. + */ + + { PRESHIFT(0x00000000) /* 0.000000000 */, /* 0 */ + -PRESHIFT(0x0001d000) /* -0.000442505 */, + PRESHIFT(0x000d5000) /* 0.003250122 */, + -PRESHIFT(0x001cb000) /* -0.007003784 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + -PRESHIFT(0x01421000) /* -0.078628540 */, + PRESHIFT(0x019ae000) /* 0.100311279 */, + -PRESHIFT(0x09271000) /* -0.572036743 */, + PRESHIFT(0x1251e000) /* 1.144989014 */, + PRESHIFT(0x09271000) /* 0.572036743 */, + PRESHIFT(0x019ae000) /* 0.100311279 */, + PRESHIFT(0x01421000) /* 0.078628540 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + PRESHIFT(0x001cb000) /* 0.007003784 */, + PRESHIFT(0x000d5000) /* 0.003250122 */, + PRESHIFT(0x0001d000) /* 0.000442505 */, + + PRESHIFT(0x00000000) /* 0.000000000 */, + -PRESHIFT(0x0001d000) /* -0.000442505 */, + PRESHIFT(0x000d5000) /* 0.003250122 */, + -PRESHIFT(0x001cb000) /* -0.007003784 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + -PRESHIFT(0x01421000) /* -0.078628540 */, + PRESHIFT(0x019ae000) /* 0.100311279 */, + -PRESHIFT(0x09271000) /* -0.572036743 */, + PRESHIFT(0x1251e000) /* 1.144989014 */, + PRESHIFT(0x09271000) /* 0.572036743 */, + PRESHIFT(0x019ae000) /* 0.100311279 */, + PRESHIFT(0x01421000) /* 0.078628540 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + PRESHIFT(0x001cb000) /* 0.007003784 */, + PRESHIFT(0x000d5000) /* 0.003250122 */, + PRESHIFT(0x0001d000) /* 0.000442505 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 1 */ + -PRESHIFT(0x0001f000) /* -0.000473022 */, + PRESHIFT(0x000da000) /* 0.003326416 */, + -PRESHIFT(0x00207000) /* -0.007919312 */, + PRESHIFT(0x007d0000) /* 0.030517578 */, + -PRESHIFT(0x0158d000) /* -0.084182739 */, + PRESHIFT(0x01747000) /* 0.090927124 */, + -PRESHIFT(0x099a8000) /* -0.600219727 */, + PRESHIFT(0x124f0000) /* 1.144287109 */, + PRESHIFT(0x08b38000) /* 0.543823242 */, + PRESHIFT(0x01bde000) /* 0.108856201 */, + PRESHIFT(0x012b4000) /* 0.073059082 */, + PRESHIFT(0x0080f000) /* 0.031478882 */, + PRESHIFT(0x00191000) /* 0.006118774 */, + PRESHIFT(0x000d0000) /* 0.003173828 */, + PRESHIFT(0x0001a000) /* 0.000396729 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x0001f000) /* -0.000473022 */, + PRESHIFT(0x000da000) /* 0.003326416 */, + -PRESHIFT(0x00207000) /* -0.007919312 */, + PRESHIFT(0x007d0000) /* 0.030517578 */, + -PRESHIFT(0x0158d000) /* -0.084182739 */, + PRESHIFT(0x01747000) /* 0.090927124 */, + -PRESHIFT(0x099a8000) /* -0.600219727 */, + PRESHIFT(0x124f0000) /* 1.144287109 */, + PRESHIFT(0x08b38000) /* 0.543823242 */, + PRESHIFT(0x01bde000) /* 0.108856201 */, + PRESHIFT(0x012b4000) /* 0.073059082 */, + PRESHIFT(0x0080f000) /* 0.031478882 */, + PRESHIFT(0x00191000) /* 0.006118774 */, + PRESHIFT(0x000d0000) /* 0.003173828 */, + PRESHIFT(0x0001a000) /* 0.000396729 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 2 */ + -PRESHIFT(0x00023000) /* -0.000534058 */, + PRESHIFT(0x000de000) /* 0.003387451 */, + -PRESHIFT(0x00245000) /* -0.008865356 */, + PRESHIFT(0x007a0000) /* 0.029785156 */, + -PRESHIFT(0x016f7000) /* -0.089706421 */, + PRESHIFT(0x014a8000) /* 0.080688477 */, + -PRESHIFT(0x0a0d8000) /* -0.628295898 */, + PRESHIFT(0x12468000) /* 1.142211914 */, + PRESHIFT(0x083ff000) /* 0.515609741 */, + PRESHIFT(0x01dd8000) /* 0.116577148 */, + PRESHIFT(0x01149000) /* 0.067520142 */, + PRESHIFT(0x00820000) /* 0.031738281 */, + PRESHIFT(0x0015b000) /* 0.005294800 */, + PRESHIFT(0x000ca000) /* 0.003082275 */, + PRESHIFT(0x00018000) /* 0.000366211 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x00023000) /* -0.000534058 */, + PRESHIFT(0x000de000) /* 0.003387451 */, + -PRESHIFT(0x00245000) /* -0.008865356 */, + PRESHIFT(0x007a0000) /* 0.029785156 */, + -PRESHIFT(0x016f7000) /* -0.089706421 */, + PRESHIFT(0x014a8000) /* 0.080688477 */, + -PRESHIFT(0x0a0d8000) /* -0.628295898 */, + PRESHIFT(0x12468000) /* 1.142211914 */, + PRESHIFT(0x083ff000) /* 0.515609741 */, + PRESHIFT(0x01dd8000) /* 0.116577148 */, + PRESHIFT(0x01149000) /* 0.067520142 */, + PRESHIFT(0x00820000) /* 0.031738281 */, + PRESHIFT(0x0015b000) /* 0.005294800 */, + PRESHIFT(0x000ca000) /* 0.003082275 */, + PRESHIFT(0x00018000) /* 0.000366211 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 3 */ + -PRESHIFT(0x00026000) /* -0.000579834 */, + PRESHIFT(0x000e1000) /* 0.003433228 */, + -PRESHIFT(0x00285000) /* -0.009841919 */, + PRESHIFT(0x00765000) /* 0.028884888 */, + -PRESHIFT(0x0185d000) /* -0.095169067 */, + PRESHIFT(0x011d1000) /* 0.069595337 */, + -PRESHIFT(0x0a7fe000) /* -0.656219482 */, + PRESHIFT(0x12386000) /* 1.138763428 */, + PRESHIFT(0x07ccb000) /* 0.487472534 */, + PRESHIFT(0x01f9c000) /* 0.123474121 */, + PRESHIFT(0x00fdf000) /* 0.061996460 */, + PRESHIFT(0x00827000) /* 0.031845093 */, + PRESHIFT(0x00126000) /* 0.004486084 */, + PRESHIFT(0x000c4000) /* 0.002990723 */, + PRESHIFT(0x00015000) /* 0.000320435 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x00026000) /* -0.000579834 */, + PRESHIFT(0x000e1000) /* 0.003433228 */, + -PRESHIFT(0x00285000) /* -0.009841919 */, + PRESHIFT(0x00765000) /* 0.028884888 */, + -PRESHIFT(0x0185d000) /* -0.095169067 */, + PRESHIFT(0x011d1000) /* 0.069595337 */, + -PRESHIFT(0x0a7fe000) /* -0.656219482 */, + PRESHIFT(0x12386000) /* 1.138763428 */, + PRESHIFT(0x07ccb000) /* 0.487472534 */, + PRESHIFT(0x01f9c000) /* 0.123474121 */, + PRESHIFT(0x00fdf000) /* 0.061996460 */, + PRESHIFT(0x00827000) /* 0.031845093 */, + PRESHIFT(0x00126000) /* 0.004486084 */, + PRESHIFT(0x000c4000) /* 0.002990723 */, + PRESHIFT(0x00015000) /* 0.000320435 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 4 */ + -PRESHIFT(0x00029000) /* -0.000625610 */, + PRESHIFT(0x000e3000) /* 0.003463745 */, + -PRESHIFT(0x002c7000) /* -0.010848999 */, + PRESHIFT(0x0071e000) /* 0.027801514 */, + -PRESHIFT(0x019bd000) /* -0.100540161 */, + PRESHIFT(0x00ec0000) /* 0.057617187 */, + -PRESHIFT(0x0af15000) /* -0.683914185 */, + PRESHIFT(0x12249000) /* 1.133926392 */, + PRESHIFT(0x075a0000) /* 0.459472656 */, + PRESHIFT(0x0212c000) /* 0.129577637 */, + PRESHIFT(0x00e79000) /* 0.056533813 */, + PRESHIFT(0x00825000) /* 0.031814575 */, + PRESHIFT(0x000f4000) /* 0.003723145 */, + PRESHIFT(0x000be000) /* 0.002899170 */, + PRESHIFT(0x00013000) /* 0.000289917 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x00029000) /* -0.000625610 */, + PRESHIFT(0x000e3000) /* 0.003463745 */, + -PRESHIFT(0x002c7000) /* -0.010848999 */, + PRESHIFT(0x0071e000) /* 0.027801514 */, + -PRESHIFT(0x019bd000) /* -0.100540161 */, + PRESHIFT(0x00ec0000) /* 0.057617187 */, + -PRESHIFT(0x0af15000) /* -0.683914185 */, + PRESHIFT(0x12249000) /* 1.133926392 */, + PRESHIFT(0x075a0000) /* 0.459472656 */, + PRESHIFT(0x0212c000) /* 0.129577637 */, + PRESHIFT(0x00e79000) /* 0.056533813 */, + PRESHIFT(0x00825000) /* 0.031814575 */, + PRESHIFT(0x000f4000) /* 0.003723145 */, + PRESHIFT(0x000be000) /* 0.002899170 */, + PRESHIFT(0x00013000) /* 0.000289917 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 5 */ + -PRESHIFT(0x0002d000) /* -0.000686646 */, + PRESHIFT(0x000e4000) /* 0.003479004 */, + -PRESHIFT(0x0030b000) /* -0.011886597 */, + PRESHIFT(0x006cb000) /* 0.026535034 */, + -PRESHIFT(0x01b17000) /* -0.105819702 */, + PRESHIFT(0x00b77000) /* 0.044784546 */, + -PRESHIFT(0x0b619000) /* -0.711318970 */, + PRESHIFT(0x120b4000) /* 1.127746582 */, + PRESHIFT(0x06e81000) /* 0.431655884 */, + PRESHIFT(0x02288000) /* 0.134887695 */, + PRESHIFT(0x00d17000) /* 0.051132202 */, + PRESHIFT(0x0081b000) /* 0.031661987 */, + PRESHIFT(0x000c5000) /* 0.003005981 */, + PRESHIFT(0x000b7000) /* 0.002792358 */, + PRESHIFT(0x00011000) /* 0.000259399 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x0002d000) /* -0.000686646 */, + PRESHIFT(0x000e4000) /* 0.003479004 */, + -PRESHIFT(0x0030b000) /* -0.011886597 */, + PRESHIFT(0x006cb000) /* 0.026535034 */, + -PRESHIFT(0x01b17000) /* -0.105819702 */, + PRESHIFT(0x00b77000) /* 0.044784546 */, + -PRESHIFT(0x0b619000) /* -0.711318970 */, + PRESHIFT(0x120b4000) /* 1.127746582 */, + PRESHIFT(0x06e81000) /* 0.431655884 */, + PRESHIFT(0x02288000) /* 0.134887695 */, + PRESHIFT(0x00d17000) /* 0.051132202 */, + PRESHIFT(0x0081b000) /* 0.031661987 */, + PRESHIFT(0x000c5000) /* 0.003005981 */, + PRESHIFT(0x000b7000) /* 0.002792358 */, + PRESHIFT(0x00011000) /* 0.000259399 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 6 */ + -PRESHIFT(0x00031000) /* -0.000747681 */, + PRESHIFT(0x000e4000) /* 0.003479004 */, + -PRESHIFT(0x00350000) /* -0.012939453 */, + PRESHIFT(0x0066c000) /* 0.025085449 */, + -PRESHIFT(0x01c67000) /* -0.110946655 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + -PRESHIFT(0x0bd06000) /* -0.738372803 */, + PRESHIFT(0x11ec7000) /* 1.120223999 */, + PRESHIFT(0x06772000) /* 0.404083252 */, + PRESHIFT(0x023b3000) /* 0.139450073 */, + PRESHIFT(0x00bbc000) /* 0.045837402 */, + PRESHIFT(0x00809000) /* 0.031387329 */, + PRESHIFT(0x00099000) /* 0.002334595 */, + PRESHIFT(0x000b0000) /* 0.002685547 */, + PRESHIFT(0x00010000) /* 0.000244141 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x00031000) /* -0.000747681 */, + PRESHIFT(0x000e4000) /* 0.003479004 */, + -PRESHIFT(0x00350000) /* -0.012939453 */, + PRESHIFT(0x0066c000) /* 0.025085449 */, + -PRESHIFT(0x01c67000) /* -0.110946655 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + -PRESHIFT(0x0bd06000) /* -0.738372803 */, + PRESHIFT(0x11ec7000) /* 1.120223999 */, + PRESHIFT(0x06772000) /* 0.404083252 */, + PRESHIFT(0x023b3000) /* 0.139450073 */, + PRESHIFT(0x00bbc000) /* 0.045837402 */, + PRESHIFT(0x00809000) /* 0.031387329 */, + PRESHIFT(0x00099000) /* 0.002334595 */, + PRESHIFT(0x000b0000) /* 0.002685547 */, + PRESHIFT(0x00010000) /* 0.000244141 */ }, + + { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 7 */ + -PRESHIFT(0x00035000) /* -0.000808716 */, + PRESHIFT(0x000e3000) /* 0.003463745 */, + -PRESHIFT(0x00397000) /* -0.014022827 */, + PRESHIFT(0x005ff000) /* 0.023422241 */, + -PRESHIFT(0x01dad000) /* -0.115921021 */, + PRESHIFT(0x0043a000) /* 0.016510010 */, + -PRESHIFT(0x0c3d9000) /* -0.765029907 */, + PRESHIFT(0x11c83000) /* 1.111373901 */, + PRESHIFT(0x06076000) /* 0.376800537 */, + PRESHIFT(0x024ad000) /* 0.143264771 */, + PRESHIFT(0x00a67000) /* 0.040634155 */, + PRESHIFT(0x007f0000) /* 0.031005859 */, + PRESHIFT(0x0006f000) /* 0.001693726 */, + PRESHIFT(0x000a9000) /* 0.002578735 */, + PRESHIFT(0x0000e000) /* 0.000213623 */, + + -PRESHIFT(0x00002000) /* -0.000030518 */, + -PRESHIFT(0x00035000) /* -0.000808716 */, + PRESHIFT(0x000e3000) /* 0.003463745 */, + -PRESHIFT(0x00397000) /* -0.014022827 */, + PRESHIFT(0x005ff000) /* 0.023422241 */, + -PRESHIFT(0x01dad000) /* -0.115921021 */, + PRESHIFT(0x0043a000) /* 0.016510010 */, + -PRESHIFT(0x0c3d9000) /* -0.765029907 */, + PRESHIFT(0x11c83000) /* 1.111373901 */, + PRESHIFT(0x06076000) /* 0.376800537 */, + PRESHIFT(0x024ad000) /* 0.143264771 */, + PRESHIFT(0x00a67000) /* 0.040634155 */, + PRESHIFT(0x007f0000) /* 0.031005859 */, + PRESHIFT(0x0006f000) /* 0.001693726 */, + PRESHIFT(0x000a9000) /* 0.002578735 */, + PRESHIFT(0x0000e000) /* 0.000213623 */ }, + + { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 8 */ + -PRESHIFT(0x0003a000) /* -0.000885010 */, + PRESHIFT(0x000e0000) /* 0.003417969 */, + -PRESHIFT(0x003df000) /* -0.015121460 */, + PRESHIFT(0x00586000) /* 0.021575928 */, + -PRESHIFT(0x01ee6000) /* -0.120697021 */, + PRESHIFT(0x00046000) /* 0.001068115 */, + -PRESHIFT(0x0ca8d000) /* -0.791213989 */, + PRESHIFT(0x119e9000) /* 1.101211548 */, + PRESHIFT(0x05991000) /* 0.349868774 */, + PRESHIFT(0x02578000) /* 0.146362305 */, + PRESHIFT(0x0091a000) /* 0.035552979 */, + PRESHIFT(0x007d1000) /* 0.030532837 */, + PRESHIFT(0x00048000) /* 0.001098633 */, + PRESHIFT(0x000a1000) /* 0.002456665 */, + PRESHIFT(0x0000d000) /* 0.000198364 */, + + -PRESHIFT(0x00002000) /* -0.000030518 */, + -PRESHIFT(0x0003a000) /* -0.000885010 */, + PRESHIFT(0x000e0000) /* 0.003417969 */, + -PRESHIFT(0x003df000) /* -0.015121460 */, + PRESHIFT(0x00586000) /* 0.021575928 */, + -PRESHIFT(0x01ee6000) /* -0.120697021 */, + PRESHIFT(0x00046000) /* 0.001068115 */, + -PRESHIFT(0x0ca8d000) /* -0.791213989 */, + PRESHIFT(0x119e9000) /* 1.101211548 */, + PRESHIFT(0x05991000) /* 0.349868774 */, + PRESHIFT(0x02578000) /* 0.146362305 */, + PRESHIFT(0x0091a000) /* 0.035552979 */, + PRESHIFT(0x007d1000) /* 0.030532837 */, + PRESHIFT(0x00048000) /* 0.001098633 */, + PRESHIFT(0x000a1000) /* 0.002456665 */, + PRESHIFT(0x0000d000) /* 0.000198364 */ }, + + { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 9 */ + -PRESHIFT(0x0003f000) /* -0.000961304 */, + PRESHIFT(0x000dd000) /* 0.003372192 */, + -PRESHIFT(0x00428000) /* -0.016235352 */, + PRESHIFT(0x00500000) /* 0.019531250 */, + -PRESHIFT(0x02011000) /* -0.125259399 */, + -PRESHIFT(0x003e6000) /* -0.015228271 */, + -PRESHIFT(0x0d11e000) /* -0.816864014 */, + PRESHIFT(0x116fc000) /* 1.089782715 */, + PRESHIFT(0x052c5000) /* 0.323318481 */, + PRESHIFT(0x02616000) /* 0.148773193 */, + PRESHIFT(0x007d6000) /* 0.030609131 */, + PRESHIFT(0x007aa000) /* 0.029937744 */, + PRESHIFT(0x00024000) /* 0.000549316 */, + PRESHIFT(0x0009a000) /* 0.002349854 */, + PRESHIFT(0x0000b000) /* 0.000167847 */, + + -PRESHIFT(0x00002000) /* -0.000030518 */, + -PRESHIFT(0x0003f000) /* -0.000961304 */, + PRESHIFT(0x000dd000) /* 0.003372192 */, + -PRESHIFT(0x00428000) /* -0.016235352 */, + PRESHIFT(0x00500000) /* 0.019531250 */, + -PRESHIFT(0x02011000) /* -0.125259399 */, + -PRESHIFT(0x003e6000) /* -0.015228271 */, + -PRESHIFT(0x0d11e000) /* -0.816864014 */, + PRESHIFT(0x116fc000) /* 1.089782715 */, + PRESHIFT(0x052c5000) /* 0.323318481 */, + PRESHIFT(0x02616000) /* 0.148773193 */, + PRESHIFT(0x007d6000) /* 0.030609131 */, + PRESHIFT(0x007aa000) /* 0.029937744 */, + PRESHIFT(0x00024000) /* 0.000549316 */, + PRESHIFT(0x0009a000) /* 0.002349854 */, + PRESHIFT(0x0000b000) /* 0.000167847 */ }, + + { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 10 */ + -PRESHIFT(0x00044000) /* -0.001037598 */, + PRESHIFT(0x000d7000) /* 0.003280640 */, + -PRESHIFT(0x00471000) /* -0.017349243 */, + PRESHIFT(0x0046b000) /* 0.017257690 */, + -PRESHIFT(0x0212b000) /* -0.129562378 */, + -PRESHIFT(0x0084a000) /* -0.032379150 */, + -PRESHIFT(0x0d78a000) /* -0.841949463 */, + PRESHIFT(0x113be000) /* 1.077117920 */, + PRESHIFT(0x04c16000) /* 0.297210693 */, + PRESHIFT(0x02687000) /* 0.150497437 */, + PRESHIFT(0x0069c000) /* 0.025817871 */, + PRESHIFT(0x0077f000) /* 0.029281616 */, + PRESHIFT(0x00002000) /* 0.000030518 */, + PRESHIFT(0x00093000) /* 0.002243042 */, + PRESHIFT(0x0000a000) /* 0.000152588 */, + + -PRESHIFT(0x00002000) /* -0.000030518 */, + -PRESHIFT(0x00044000) /* -0.001037598 */, + PRESHIFT(0x000d7000) /* 0.003280640 */, + -PRESHIFT(0x00471000) /* -0.017349243 */, + PRESHIFT(0x0046b000) /* 0.017257690 */, + -PRESHIFT(0x0212b000) /* -0.129562378 */, + -PRESHIFT(0x0084a000) /* -0.032379150 */, + -PRESHIFT(0x0d78a000) /* -0.841949463 */, + PRESHIFT(0x113be000) /* 1.077117920 */, + PRESHIFT(0x04c16000) /* 0.297210693 */, + PRESHIFT(0x02687000) /* 0.150497437 */, + PRESHIFT(0x0069c000) /* 0.025817871 */, + PRESHIFT(0x0077f000) /* 0.029281616 */, + PRESHIFT(0x00002000) /* 0.000030518 */, + PRESHIFT(0x00093000) /* 0.002243042 */, + PRESHIFT(0x0000a000) /* 0.000152588 */ }, + + { -PRESHIFT(0x00003000) /* -0.000045776 */, /* 11 */ + -PRESHIFT(0x00049000) /* -0.001113892 */, + PRESHIFT(0x000d0000) /* 0.003173828 */, + -PRESHIFT(0x004ba000) /* -0.018463135 */, + PRESHIFT(0x003ca000) /* 0.014801025 */, + -PRESHIFT(0x02233000) /* -0.133590698 */, + -PRESHIFT(0x00ce4000) /* -0.050354004 */, + -PRESHIFT(0x0ddca000) /* -0.866363525 */, + PRESHIFT(0x1102f000) /* 1.063217163 */, + PRESHIFT(0x04587000) /* 0.271591187 */, + PRESHIFT(0x026cf000) /* 0.151596069 */, + PRESHIFT(0x0056c000) /* 0.021179199 */, + PRESHIFT(0x0074e000) /* 0.028533936 */, + -PRESHIFT(0x0001d000) /* -0.000442505 */, + PRESHIFT(0x0008b000) /* 0.002120972 */, + PRESHIFT(0x00009000) /* 0.000137329 */, + + -PRESHIFT(0x00003000) /* -0.000045776 */, + -PRESHIFT(0x00049000) /* -0.001113892 */, + PRESHIFT(0x000d0000) /* 0.003173828 */, + -PRESHIFT(0x004ba000) /* -0.018463135 */, + PRESHIFT(0x003ca000) /* 0.014801025 */, + -PRESHIFT(0x02233000) /* -0.133590698 */, + -PRESHIFT(0x00ce4000) /* -0.050354004 */, + -PRESHIFT(0x0ddca000) /* -0.866363525 */, + PRESHIFT(0x1102f000) /* 1.063217163 */, + PRESHIFT(0x04587000) /* 0.271591187 */, + PRESHIFT(0x026cf000) /* 0.151596069 */, + PRESHIFT(0x0056c000) /* 0.021179199 */, + PRESHIFT(0x0074e000) /* 0.028533936 */, + -PRESHIFT(0x0001d000) /* -0.000442505 */, + PRESHIFT(0x0008b000) /* 0.002120972 */, + PRESHIFT(0x00009000) /* 0.000137329 */ }, + + { -PRESHIFT(0x00003000) /* -0.000045776 */, /* 12 */ + -PRESHIFT(0x0004f000) /* -0.001205444 */, + PRESHIFT(0x000c8000) /* 0.003051758 */, + -PRESHIFT(0x00503000) /* -0.019577026 */, + PRESHIFT(0x0031a000) /* 0.012115479 */, + -PRESHIFT(0x02326000) /* -0.137298584 */, + -PRESHIFT(0x011b5000) /* -0.069168091 */, + -PRESHIFT(0x0e3dd000) /* -0.890090942 */, + PRESHIFT(0x10c54000) /* 1.048156738 */, + PRESHIFT(0x03f1b000) /* 0.246505737 */, + PRESHIFT(0x026ee000) /* 0.152069092 */, + PRESHIFT(0x00447000) /* 0.016708374 */, + PRESHIFT(0x00719000) /* 0.027725220 */, + -PRESHIFT(0x00039000) /* -0.000869751 */, + PRESHIFT(0x00084000) /* 0.002014160 */, + PRESHIFT(0x00008000) /* 0.000122070 */, + + -PRESHIFT(0x00003000) /* -0.000045776 */, + -PRESHIFT(0x0004f000) /* -0.001205444 */, + PRESHIFT(0x000c8000) /* 0.003051758 */, + -PRESHIFT(0x00503000) /* -0.019577026 */, + PRESHIFT(0x0031a000) /* 0.012115479 */, + -PRESHIFT(0x02326000) /* -0.137298584 */, + -PRESHIFT(0x011b5000) /* -0.069168091 */, + -PRESHIFT(0x0e3dd000) /* -0.890090942 */, + PRESHIFT(0x10c54000) /* 1.048156738 */, + PRESHIFT(0x03f1b000) /* 0.246505737 */, + PRESHIFT(0x026ee000) /* 0.152069092 */, + PRESHIFT(0x00447000) /* 0.016708374 */, + PRESHIFT(0x00719000) /* 0.027725220 */, + -PRESHIFT(0x00039000) /* -0.000869751 */, + PRESHIFT(0x00084000) /* 0.002014160 */, + PRESHIFT(0x00008000) /* 0.000122070 */ }, + + { -PRESHIFT(0x00004000) /* -0.000061035 */, /* 13 */ + -PRESHIFT(0x00055000) /* -0.001296997 */, + PRESHIFT(0x000bd000) /* 0.002883911 */, + -PRESHIFT(0x0054c000) /* -0.020690918 */, + PRESHIFT(0x0025d000) /* 0.009231567 */, + -PRESHIFT(0x02403000) /* -0.140670776 */, + -PRESHIFT(0x016ba000) /* -0.088775635 */, + -PRESHIFT(0x0e9be000) /* -0.913055420 */, + PRESHIFT(0x1082d000) /* 1.031936646 */, + PRESHIFT(0x038d4000) /* 0.221984863 */, + PRESHIFT(0x026e7000) /* 0.151962280 */, + PRESHIFT(0x0032e000) /* 0.012420654 */, + PRESHIFT(0x006df000) /* 0.026840210 */, + -PRESHIFT(0x00053000) /* -0.001266479 */, + PRESHIFT(0x0007d000) /* 0.001907349 */, + PRESHIFT(0x00007000) /* 0.000106812 */, + + -PRESHIFT(0x00004000) /* -0.000061035 */, + -PRESHIFT(0x00055000) /* -0.001296997 */, + PRESHIFT(0x000bd000) /* 0.002883911 */, + -PRESHIFT(0x0054c000) /* -0.020690918 */, + PRESHIFT(0x0025d000) /* 0.009231567 */, + -PRESHIFT(0x02403000) /* -0.140670776 */, + -PRESHIFT(0x016ba000) /* -0.088775635 */, + -PRESHIFT(0x0e9be000) /* -0.913055420 */, + PRESHIFT(0x1082d000) /* 1.031936646 */, + PRESHIFT(0x038d4000) /* 0.221984863 */, + PRESHIFT(0x026e7000) /* 0.151962280 */, + PRESHIFT(0x0032e000) /* 0.012420654 */, + PRESHIFT(0x006df000) /* 0.026840210 */, + -PRESHIFT(0x00053000) /* -0.001266479 */, + PRESHIFT(0x0007d000) /* 0.001907349 */, + PRESHIFT(0x00007000) /* 0.000106812 */ }, + + { -PRESHIFT(0x00004000) /* -0.000061035 */, /* 14 */ + -PRESHIFT(0x0005b000) /* -0.001388550 */, + PRESHIFT(0x000b1000) /* 0.002700806 */, + -PRESHIFT(0x00594000) /* -0.021789551 */, + PRESHIFT(0x00192000) /* 0.006134033 */, + -PRESHIFT(0x024c8000) /* -0.143676758 */, + -PRESHIFT(0x01bf2000) /* -0.109161377 */, + -PRESHIFT(0x0ef69000) /* -0.935195923 */, + PRESHIFT(0x103be000) /* 1.014617920 */, + PRESHIFT(0x032b4000) /* 0.198059082 */, + PRESHIFT(0x026bc000) /* 0.151306152 */, + PRESHIFT(0x00221000) /* 0.008316040 */, + PRESHIFT(0x006a2000) /* 0.025909424 */, + -PRESHIFT(0x0006a000) /* -0.001617432 */, + PRESHIFT(0x00075000) /* 0.001785278 */, + PRESHIFT(0x00007000) /* 0.000106812 */, + + -PRESHIFT(0x00004000) /* -0.000061035 */, + -PRESHIFT(0x0005b000) /* -0.001388550 */, + PRESHIFT(0x000b1000) /* 0.002700806 */, + -PRESHIFT(0x00594000) /* -0.021789551 */, + PRESHIFT(0x00192000) /* 0.006134033 */, + -PRESHIFT(0x024c8000) /* -0.143676758 */, + -PRESHIFT(0x01bf2000) /* -0.109161377 */, + -PRESHIFT(0x0ef69000) /* -0.935195923 */, + PRESHIFT(0x103be000) /* 1.014617920 */, + PRESHIFT(0x032b4000) /* 0.198059082 */, + PRESHIFT(0x026bc000) /* 0.151306152 */, + PRESHIFT(0x00221000) /* 0.008316040 */, + PRESHIFT(0x006a2000) /* 0.025909424 */, + -PRESHIFT(0x0006a000) /* -0.001617432 */, + PRESHIFT(0x00075000) /* 0.001785278 */, + PRESHIFT(0x00007000) /* 0.000106812 */ }, + + { -PRESHIFT(0x00005000) /* -0.000076294 */, /* 15 */ + -PRESHIFT(0x00061000) /* -0.001480103 */, + PRESHIFT(0x000a3000) /* 0.002487183 */, + -PRESHIFT(0x005da000) /* -0.022857666 */, + PRESHIFT(0x000b9000) /* 0.002822876 */, + -PRESHIFT(0x02571000) /* -0.146255493 */, + -PRESHIFT(0x0215c000) /* -0.130310059 */, + -PRESHIFT(0x0f4dc000) /* -0.956481934 */, + PRESHIFT(0x0ff0a000) /* 0.996246338 */, + PRESHIFT(0x02cbf000) /* 0.174789429 */, + PRESHIFT(0x0266e000) /* 0.150115967 */, + PRESHIFT(0x00120000) /* 0.004394531 */, + PRESHIFT(0x00662000) /* 0.024932861 */, + -PRESHIFT(0x0007f000) /* -0.001937866 */, + PRESHIFT(0x0006f000) /* 0.001693726 */, + PRESHIFT(0x00006000) /* 0.000091553 */, + + -PRESHIFT(0x00005000) /* -0.000076294 */, + -PRESHIFT(0x00061000) /* -0.001480103 */, + PRESHIFT(0x000a3000) /* 0.002487183 */, + -PRESHIFT(0x005da000) /* -0.022857666 */, + PRESHIFT(0x000b9000) /* 0.002822876 */, + -PRESHIFT(0x02571000) /* -0.146255493 */, + -PRESHIFT(0x0215c000) /* -0.130310059 */, + -PRESHIFT(0x0f4dc000) /* -0.956481934 */, + PRESHIFT(0x0ff0a000) /* 0.996246338 */, + PRESHIFT(0x02cbf000) /* 0.174789429 */, + PRESHIFT(0x0266e000) /* 0.150115967 */, + PRESHIFT(0x00120000) /* 0.004394531 */, + PRESHIFT(0x00662000) /* 0.024932861 */, + -PRESHIFT(0x0007f000) /* -0.001937866 */, + PRESHIFT(0x0006f000) /* 0.001693726 */, + PRESHIFT(0x00006000) /* 0.000091553 */ }, + + { -PRESHIFT(0x00005000) /* -0.000076294 */, /* 16 */ + -PRESHIFT(0x00068000) /* -0.001586914 */, + PRESHIFT(0x00092000) /* 0.002227783 */, + -PRESHIFT(0x0061f000) /* -0.023910522 */, + -PRESHIFT(0x0002d000) /* -0.000686646 */, + -PRESHIFT(0x025ff000) /* -0.148422241 */, + -PRESHIFT(0x026f7000) /* -0.152206421 */, + -PRESHIFT(0x0fa13000) /* -0.976852417 */, + PRESHIFT(0x0fa13000) /* 0.976852417 */, + PRESHIFT(0x026f7000) /* 0.152206421 */, + PRESHIFT(0x025ff000) /* 0.148422241 */, + PRESHIFT(0x0002d000) /* 0.000686646 */, + PRESHIFT(0x0061f000) /* 0.023910522 */, + -PRESHIFT(0x00092000) /* -0.002227783 */, + PRESHIFT(0x00068000) /* 0.001586914 */, + PRESHIFT(0x00005000) /* 0.000076294 */, + + -PRESHIFT(0x00005000) /* -0.000076294 */, + -PRESHIFT(0x00068000) /* -0.001586914 */, + PRESHIFT(0x00092000) /* 0.002227783 */, + -PRESHIFT(0x0061f000) /* -0.023910522 */, + -PRESHIFT(0x0002d000) /* -0.000686646 */, + -PRESHIFT(0x025ff000) /* -0.148422241 */, + -PRESHIFT(0x026f7000) /* -0.152206421 */, + -PRESHIFT(0x0fa13000) /* -0.976852417 */, + PRESHIFT(0x0fa13000) /* 0.976852417 */, + PRESHIFT(0x026f7000) /* 0.152206421 */, + PRESHIFT(0x025ff000) /* 0.148422241 */, + PRESHIFT(0x0002d000) /* 0.000686646 */, + PRESHIFT(0x0061f000) /* 0.023910522 */, + -PRESHIFT(0x00092000) /* -0.002227783 */, + PRESHIFT(0x00068000) /* 0.001586914 */, + PRESHIFT(0x00005000) /* 0.000076294 */ } diff --git a/core/multimedia/opieplayer/libmad/Makefile.in b/core/multimedia/opieplayer/libmad/Makefile.in new file mode 100644 index 0000000..9e17769 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/Makefile.in @@ -0,0 +1,226 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB) -DQCONFIG=\"qpe\" +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB) -DQCONFIG=\"qpe\" +INCPATH = -I$(QPEDIR)/include -I.. +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe -lm $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../../plugins/codecs/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = madplugin +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = libmad_version.h \ + fixed.h \ + bit.h \ + timer.h \ + stream.h \ + frame.h \ + synth.h \ + decoder.h \ + layer12.h \ + layer3.h \ + huffman.h \ + libmad_global.h \ + mad.h \ + libmadplugin.h \ + libmadpluginimpl.h +SOURCES = version.c \ + fixed.c \ + bit.c \ + timer.c \ + stream.c \ + frame.c \ + synth.c \ + decoder.c \ + layer12.c \ + layer3.c \ + huffman.c \ + libmadplugin.cpp \ + libmadpluginimpl.cpp +OBJECTS = version.o \ + fixed.o \ + bit.o \ + timer.o \ + stream.o \ + frame.o \ + synth.o \ + decoder.o \ + layer12.o \ + layer3.o \ + huffman.o \ + libmadplugin.o \ + libmadpluginimpl.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = +OBJMOC = + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(SYSCONF_LINK_TARGET) + +$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK_LIB) + +moc: $(SRCMOC) + +tmake: + tmake libmad.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +version.o: version.c \ + libmad_global.h \ + libmad_version.h + +fixed.o: fixed.c \ + libmad_global.h \ + fixed.h + +bit.o: bit.c \ + libmad_global.h \ + bit.h + +timer.o: timer.c \ + libmad_global.h \ + timer.h + +stream.o: stream.c \ + libmad_global.h \ + bit.h \ + stream.h + +frame.o: frame.c \ + libmad_global.h \ + bit.h \ + stream.h \ + frame.h \ + fixed.h \ + timer.h \ + layer12.h \ + layer3.h + +synth.o: synth.c \ + libmad_global.h \ + fixed.h \ + frame.h \ + timer.h \ + stream.h \ + bit.h \ + synth.h \ + D.dat + +decoder.o: decoder.c \ + libmad_global.h \ + stream.h \ + bit.h \ + frame.h \ + fixed.h \ + timer.h \ + synth.h \ + decoder.h + +layer12.o: layer12.c \ + libmad_global.h \ + fixed.h \ + bit.h \ + stream.h \ + frame.h \ + timer.h \ + layer12.h \ + sf_table.dat \ + qc_table.dat + +layer3.o: layer3.c \ + libmad_global.h \ + fixed.h \ + bit.h \ + stream.h \ + frame.h \ + timer.h \ + huffman.h \ + layer3.h \ + rq_table.dat \ + imdct_s.dat + +huffman.o: huffman.c \ + libmad_global.h \ + huffman.h + +libmadplugin.o: libmadplugin.cpp \ + libmadplugin.h \ + ../mediaplayerplugininterface.h \ + mad.h + +libmadpluginimpl.o: libmadpluginimpl.cpp \ + libmadplugin.h \ + ../mediaplayerplugininterface.h \ + libmadpluginimpl.h \ + ../mediaplayerplugininterface.h + + diff --git a/core/multimedia/opieplayer/libmad/bit.c b/core/multimedia/opieplayer/libmad/bit.c new file mode 100644 index 0000000..2466c5f --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/bit.c @@ -0,0 +1,220 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifdef HAVE_CONFIG_H +# include "libmad_config.h" +# endif + +# include "libmad_global.h" + +# ifdef HAVE_LIMITS_H +# include +# else +# define CHAR_BIT 8 +# endif + +# include "bit.h" + +/* + * This is the lookup table for computing the CRC-check word. + * As described in section 2.4.3.1 and depicted in Figure A.9 + * of ISO/IEC 11172-3, the generator polynomial is: + * + * G(X) = X^16 + X^15 + X^2 + 1 + */ +static +unsigned short const crc_table[256] = { + 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, + 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, + 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, + 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, + 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, + + 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, + 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, + 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, + 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, + 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, + + 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, + 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, + 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, + 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, + 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, + + 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, + 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, + 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, + 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, + 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 +}; + +# define CRC_POLY 0x8005 + +/* + * NAME: bit->init() + * DESCRIPTION: initialize bit pointer struct + */ +void mad_bit_init(struct mad_bitptr *bitptr, unsigned char const *byte) +{ + bitptr->byte = byte; + bitptr->cache = 0; + bitptr->left = CHAR_BIT; +} + +/* + * NAME: bit->length() + * DESCRIPTION: return number of bits between start and end points + */ +unsigned int mad_bit_length(struct mad_bitptr const *begin, + struct mad_bitptr const *end) +{ + return begin->left + + CHAR_BIT * (end->byte - (begin->byte + 1)) + (CHAR_BIT - end->left); +} + +/* + * NAME: bit->nextbyte() + * DESCRIPTION: return pointer to next unprocessed byte + */ +unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *bitptr) +{ + return bitptr->left == CHAR_BIT ? bitptr->byte : bitptr->byte + 1; +} + +/* + * NAME: bit->skip() + * DESCRIPTION: advance bit pointer + */ +void mad_bit_skip(struct mad_bitptr *bitptr, unsigned int len) +{ + bitptr->byte += len / CHAR_BIT; + bitptr->left -= len % CHAR_BIT; + + if (bitptr->left > CHAR_BIT) { + bitptr->byte++; + bitptr->left += CHAR_BIT; + } + + if (bitptr->left < CHAR_BIT) + bitptr->cache = *bitptr->byte; +} + +/* + * NAME: bit->read() + * DESCRIPTION: read an arbitrary number of bits and return their UIMSBF value + */ +unsigned long mad_bit_read(struct mad_bitptr *bitptr, unsigned int len) +{ + register unsigned long value; + + if (bitptr->left == CHAR_BIT) + bitptr->cache = *bitptr->byte; + + if (len < bitptr->left) { + value = (bitptr->cache & ((1 << bitptr->left) - 1)) >> + (bitptr->left - len); + bitptr->left -= len; + + return value; + } + + /* remaining bits in current byte */ + + value = bitptr->cache & ((1 << bitptr->left) - 1); + len -= bitptr->left; + + bitptr->byte++; + bitptr->left = CHAR_BIT; + + /* more bytes */ + + while (len >= CHAR_BIT) { + value = (value << CHAR_BIT) | *bitptr->byte++; + len -= CHAR_BIT; + } + + if (len > 0) { + bitptr->cache = *bitptr->byte; + + value = (value << len) | (bitptr->cache >> (CHAR_BIT - len)); + bitptr->left -= len; + } + + return value; +} + +# if 0 +/* + * NAME: bit->write() + * DESCRIPTION: write an arbitrary number of bits + */ +void mad_bit_write(struct mad_bitptr *bitptr, unsigned int len, + unsigned long value) +{ + unsigned char *ptr; + + ptr = (unsigned char *) bitptr->byte; + + /* ... */ +} +# endif + +/* + * NAME: bit->crc() + * DESCRIPTION: compute CRC-check word + */ +unsigned short mad_bit_crc(struct mad_bitptr bitptr, unsigned int len, + unsigned short init) +{ + register unsigned int crc, data; + +# if CHAR_BIT == 8 + for (crc = init; len >= 8; len -= 8) { + crc = (crc << 8) ^ + crc_table[((crc >> 8) ^ mad_bit_read(&bitptr, 8)) & 0xff]; + } +# else + crc = init; +# endif + + while (len--) { + data = mad_bit_read(&bitptr, 1) ^ (crc >> 15); + + crc <<= 1; + if (data & 1) + crc ^= CRC_POLY; + } + + return crc & 0xffff; +} diff --git a/core/multimedia/opieplayer/libmad/bit.h b/core/multimedia/opieplayer/libmad/bit.h new file mode 100644 index 0000000..f315bc9 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/bit.h @@ -0,0 +1,47 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_BIT_H +# define LIBMAD_BIT_H + +struct mad_bitptr { + unsigned char const *byte; + unsigned short cache; + unsigned short left; +}; + +void mad_bit_init(struct mad_bitptr *, unsigned char const *); + +# define mad_bit_finish(bitptr) /* nothing */ + +unsigned int mad_bit_length(struct mad_bitptr const *, + struct mad_bitptr const *); + +# define mad_bit_bitsleft(bitptr) ((bitptr)->left) +unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *); + +void mad_bit_skip(struct mad_bitptr *, unsigned int); +unsigned long mad_bit_read(struct mad_bitptr *, unsigned int); +void mad_bit_write(struct mad_bitptr *, unsigned int, unsigned long); + +unsigned short mad_bit_crc(struct mad_bitptr, unsigned int, unsigned short); + +# endif diff --git a/core/multimedia/opieplayer/libmad/decoder.c b/core/multimedia/opieplayer/libmad/decoder.c new file mode 100644 index 0000000..dcf7cf3 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/decoder.c @@ -0,0 +1,554 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifdef HAVE_CONFIG_H +# include "libmad_config.h" +# else +# ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +# endif +# ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +# endif +# endif + +# include "libmad_global.h" + +# include + +# ifdef HAVE_SYS_WAIT_H +# include +# endif + +# ifdef HAVE_UNISTD_H +# include +# endif + +# include +# include +# include + +# include "stream.h" +# include "frame.h" +# include "synth.h" +# include "decoder.h" + +void mad_decoder_init(struct mad_decoder *decoder, void *data, + enum mad_flow (*input_func)(void *, struct mad_stream *), + enum mad_flow (*header_func)(void *, + struct mad_header const *), + enum mad_flow (*filter_func)(void *, struct mad_frame *), + enum mad_flow (*output_func)(void *, + struct mad_header const *, + struct mad_pcm *), + enum mad_flow (*error_func)(void *, struct mad_stream *, + struct mad_frame *), + enum mad_flow (*message_func)(void *, + void *, unsigned int *)) +{ + decoder->mode = -1; + + decoder->options = 0; + + decoder->async.pid = 0; + decoder->async.in = -1; + decoder->async.out = -1; + + decoder->sync = 0; + + decoder->cb_data = data; + + decoder->input_func = input_func; + decoder->header_func = header_func; + decoder->filter_func = filter_func; + decoder->output_func = output_func; + decoder->error_func = error_func; + decoder->message_func = message_func; +} + +int mad_decoder_finish(struct mad_decoder *decoder) +{ + if (decoder->mode == MAD_DECODER_MODE_ASYNC && decoder->async.pid) { + pid_t pid; + int status; + + close(decoder->async.in); + + do { + pid = waitpid(decoder->async.pid, &status, 0); + } + while (pid == -1 && errno == EINTR); + + decoder->mode = -1; + + close(decoder->async.out); + + decoder->async.pid = 0; + decoder->async.in = -1; + decoder->async.out = -1; + + if (pid == -1) + return -1; + + return (!WIFEXITED(status) || WEXITSTATUS(status)) ? -1 : 0; + } + + return 0; +} + +static +enum mad_flow send_io(int fd, void const *data, size_t len) +{ + char const *ptr = data; + ssize_t count; + + while (len) { + do { + count = write(fd, ptr, len); + } + while (count == -1 && errno == EINTR); + + if (count == -1) + return MAD_FLOW_BREAK; + + len -= count; + ptr += count; + } + + return MAD_FLOW_CONTINUE; +} + +static +enum mad_flow receive_io(int fd, void *buffer, size_t len) +{ + char *ptr = buffer; + ssize_t count; + + while (len) { + do { + count = read(fd, ptr, len); + } + while (count == -1 && errno == EINTR); + + if (count == -1) + return (errno == EAGAIN) ? MAD_FLOW_IGNORE : MAD_FLOW_BREAK; + else if (count == 0) + return MAD_FLOW_STOP; + + len -= count; + ptr += count; + } + + return MAD_FLOW_CONTINUE; +} + +static +enum mad_flow receive_io_blocking(int fd, void *buffer, size_t len) +{ + int flags, blocking; + enum mad_flow result; + + flags = fcntl(fd, F_GETFL); + if (flags == -1) + return MAD_FLOW_BREAK; + + blocking = flags & ~O_NONBLOCK; + + if (blocking != flags && + fcntl(fd, F_SETFL, blocking) == -1) + return MAD_FLOW_BREAK; + + result = receive_io(fd, buffer, len); + + if (flags != blocking && + fcntl(fd, F_SETFL, flags) == -1) + return MAD_FLOW_BREAK; + + return result; +} + +static +enum mad_flow send(int fd, void const *message, unsigned int size) +{ + enum mad_flow result; + + /* send size */ + + result = send_io(fd, &size, sizeof(size)); + + /* send message */ + + if (result == MAD_FLOW_CONTINUE) + result = send_io(fd, message, size); + + return result; +} + +static +enum mad_flow receive(int fd, void **message, unsigned int *size) +{ + enum mad_flow result; + unsigned int actual; + + if (*message == 0) + *size = 0; + + /* receive size */ + + result = receive_io(fd, &actual, sizeof(actual)); + + /* receive message */ + + if (result == MAD_FLOW_CONTINUE) { + if (actual > *size) + actual -= *size; + else { + *size = actual; + actual = 0; + } + + if (*size > 0) { + if (*message == 0) { + *message = malloc(*size); + if (*message == 0) + return MAD_FLOW_BREAK; + } + + result = receive_io_blocking(fd, *message, *size); + } + + /* throw away remainder of message */ + + while (actual && result == MAD_FLOW_CONTINUE) { + char sink[256]; + unsigned int len; + + len = actual > sizeof(sink) ? sizeof(sink) : actual; + + result = receive_io_blocking(fd, sink, len); + + actual -= len; + } + } + + return result; +} + +static +enum mad_flow check_message(struct mad_decoder *decoder) +{ + enum mad_flow result; + void *message = 0; + unsigned int size; + + result = receive(decoder->async.in, &message, &size); + + if (result == MAD_FLOW_CONTINUE) { + if (decoder->message_func == 0) + size = 0; + else { + result = decoder->message_func(decoder->cb_data, message, &size); + + if (result == MAD_FLOW_IGNORE || + result == MAD_FLOW_BREAK) + size = 0; + } + + if (send(decoder->async.out, message, size) != MAD_FLOW_CONTINUE) + result = MAD_FLOW_BREAK; + } + + if (message) + free(message); + + return result; +} + +static +enum mad_flow error_default(void *data, struct mad_stream *stream, + struct mad_frame *frame) +{ + int *bad_last_frame = data; + + switch (stream->error) { + case MAD_ERROR_BADCRC: + if (*bad_last_frame) + mad_frame_mute(frame); + else + *bad_last_frame = 1; + + return MAD_FLOW_IGNORE; + + default: + return MAD_FLOW_CONTINUE; + } +} + +static +int run_sync(struct mad_decoder *decoder) +{ + enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); + void *error_data; + int bad_last_frame = 0; + struct mad_stream *stream; + struct mad_frame *frame; + struct mad_synth *synth; + int result = 0; + + if (decoder->input_func == 0) + return 0; + + if (decoder->error_func) { + error_func = decoder->error_func; + error_data = decoder->cb_data; + } + else { + error_func = error_default; + error_data = &bad_last_frame; + } + + stream = &decoder->sync->stream; + frame = &decoder->sync->frame; + synth = &decoder->sync->synth; + + mad_stream_init(stream); + mad_frame_init(frame); + mad_synth_init(synth); + + mad_stream_options(stream, decoder->options); + + do { + switch (decoder->input_func(decoder->cb_data, stream)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + continue; + case MAD_FLOW_CONTINUE: + break; + } + + while (1) { + if (decoder->mode == MAD_DECODER_MODE_ASYNC) { + switch (check_message(decoder)) { + case MAD_FLOW_IGNORE: + case MAD_FLOW_CONTINUE: + break; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_STOP: + goto done; + } + } + + if (decoder->header_func) { + if (mad_header_decode(&frame->header, stream) == -1) { + if (!MAD_RECOVERABLE(stream->error)) + break; + + switch (error_func(error_data, stream, frame)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + case MAD_FLOW_CONTINUE: + default: + continue; + } + } + + switch (decoder->header_func(decoder->cb_data, &frame->header)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + continue; + case MAD_FLOW_CONTINUE: + break; + } + } + + if (mad_frame_decode(frame, stream) == -1) { + if (!MAD_RECOVERABLE(stream->error)) + break; + + switch (error_func(error_data, stream, frame)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + break; + case MAD_FLOW_CONTINUE: + default: + continue; + } + } + else + bad_last_frame = 0; + + if (decoder->filter_func) { + switch (decoder->filter_func(decoder->cb_data, frame)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + continue; + case MAD_FLOW_CONTINUE: + break; + } + } + + mad_synth_frame(synth, frame); + + if (decoder->output_func) { + switch (decoder->output_func(decoder->cb_data, + &frame->header, &synth->pcm)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + case MAD_FLOW_CONTINUE: + break; + } + } + } + } + while (stream->error == MAD_ERROR_BUFLEN); + + fail: + result = -1; + + done: + mad_synth_finish(synth); + mad_frame_finish(frame); + mad_stream_finish(stream); + + return result; +} + +static +int run_async(struct mad_decoder *decoder) +{ + pid_t pid; + int ptoc[2], ctop[2], flags; + + if (pipe(ptoc) == -1) + return -1; + + if (pipe(ctop) == -1) { + close(ptoc[0]); + close(ptoc[1]); + return -1; + } + + flags = fcntl(ptoc[0], F_GETFL); + if (flags == -1 || + fcntl(ptoc[0], F_SETFL, flags | O_NONBLOCK) == -1) { + close(ctop[0]); + close(ctop[1]); + close(ptoc[0]); + close(ptoc[1]); + return -1; + } + + pid = fork(); + if (pid == -1) { + close(ctop[0]); + close(ctop[1]); + close(ptoc[0]); + close(ptoc[1]); + return -1; + } + + decoder->async.pid = pid; + + if (pid) { + /* parent */ + + close(ptoc[0]); + close(ctop[1]); + + decoder->async.in = ctop[0]; + decoder->async.out = ptoc[1]; + + return 0; + } + + /* child */ + + close(ptoc[1]); + close(ctop[0]); + + decoder->async.in = ptoc[0]; + decoder->async.out = ctop[1]; + + _exit(run_sync(decoder)); + + /* not reached */ + return -1; +} + +int mad_decoder_run(struct mad_decoder *decoder, enum mad_decoder_mode mode) +{ + int result; + int (*run)(struct mad_decoder *) = 0; + + switch (decoder->mode = mode) { + case MAD_DECODER_MODE_SYNC: + run = run_sync; + break; + + case MAD_DECODER_MODE_ASYNC: + run = run_async; + break; + } + + if (run == 0) + return -1; + + decoder->sync = malloc(sizeof(*decoder->sync)); + if (decoder->sync == 0) + return -1; + + result = run(decoder); + + free(decoder->sync); + decoder->sync = 0; + + return result; +} + +int mad_decoder_message(struct mad_decoder *decoder, + void *message, unsigned int *len) +{ + if (decoder->mode != MAD_DECODER_MODE_ASYNC || + send(decoder->async.out, message, *len) != MAD_FLOW_CONTINUE || + receive(decoder->async.in, &message, len) != MAD_FLOW_CONTINUE) + return -1; + + return 0; +} diff --git a/core/multimedia/opieplayer/libmad/decoder.h b/core/multimedia/opieplayer/libmad/decoder.h new file mode 100644 index 0000000..dbacc1a --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/decoder.h @@ -0,0 +1,87 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_DECODER_H +# define LIBMAD_DECODER_H + +# include "stream.h" +# include "frame.h" +# include "synth.h" + +enum mad_decoder_mode { + MAD_DECODER_MODE_SYNC = 0, + MAD_DECODER_MODE_ASYNC +}; + +enum mad_flow { + MAD_FLOW_CONTINUE = 0x0000, + MAD_FLOW_STOP = 0x0010, + MAD_FLOW_BREAK = 0x0011, + MAD_FLOW_IGNORE = 0x0020 +}; + +struct mad_decoder { + enum mad_decoder_mode mode; + + int options; + + struct { + long pid; + int in; + int out; + } async; + + struct { + struct mad_stream stream; + struct mad_frame frame; + struct mad_synth synth; + } *sync; + + void *cb_data; + + enum mad_flow (*input_func)(void *, struct mad_stream *); + enum mad_flow (*header_func)(void *, struct mad_header const *); + enum mad_flow (*filter_func)(void *, struct mad_frame *); + enum mad_flow (*output_func)(void *, + struct mad_header const *, struct mad_pcm *); + enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); + enum mad_flow (*message_func)(void *, void *, unsigned int *); +}; + +void mad_decoder_init(struct mad_decoder *, void *, + enum mad_flow (*)(void *, struct mad_stream *), + enum mad_flow (*)(void *, struct mad_header const *), + enum mad_flow (*)(void *, struct mad_frame *), + enum mad_flow (*)(void *, + struct mad_header const *, + struct mad_pcm *), + enum mad_flow (*)(void *, + struct mad_stream *, + struct mad_frame *), + enum mad_flow (*)(void *, void *, unsigned int *)); +int mad_decoder_finish(struct mad_decoder *); + +# define mad_decoder_options(decoder, opts) ((decoder)->options = (opts)) + +int mad_decoder_run(struct mad_decoder *, enum mad_decoder_mode); +int mad_decoder_message(struct mad_decoder *, void *, unsigned int *); + +# endif diff --git a/core/multimedia/opieplayer/libmad/fix_headers_problem b/core/multimedia/opieplayer/libmad/fix_headers_problem new file mode 100755 index 0000000..6a5595c --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/fix_headers_problem @@ -0,0 +1,25 @@ +#!/bin/sh + +# +# This is needed to ensure the single build will work +# The names of the header files clash with names of other headers in Qt/Palmtop +# + + +for file in *.c +do + + echo "fixing $file" + sed "s/global.h/libmad_global.h/" $file > $file.tmp + sed "s/version.h/libmad_version.h/" $file.tmp > $file + sed "s/config.h/libmad_config.h/" $file > $file.tmp + mv $file.tmp $file + +done + + +mv global.h libmad_global.h +mv version.h libmad_version.h +mv config.h libmad_config.h + + diff --git a/core/multimedia/opieplayer/libmad/fixed.c b/core/multimedia/opieplayer/libmad/fixed.c new file mode 100644 index 0000000..be5c94e --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/fixed.c @@ -0,0 +1,37 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifdef HAVE_CONFIG_H +# include "libmad_config.h" +# endif + +# include "libmad_global.h" + +# include "fixed.h" + +/* + * NAME: fixed->abs() + * DESCRIPTION: return absolute value of a fixed-point number + */ +mad_fixed_t mad_f_abs(mad_fixed_t x) +{ + return x < 0 ? -x : x; +} diff --git a/core/multimedia/opieplayer/libmad/fixed.h b/core/multimedia/opieplayer/libmad/fixed.h new file mode 100644 index 0000000..00ade62 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/fixed.h @@ -0,0 +1,413 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_FIXED_H +# define LIBMAD_FIXED_H + +# if SIZEOF_INT >= 4 +typedef signed int mad_fixed_t; + +typedef signed int mad_fixed64hi_t; +typedef unsigned int mad_fixed64lo_t; +# else +typedef signed long mad_fixed_t; + +typedef signed long mad_fixed64hi_t; +typedef unsigned long mad_fixed64lo_t; +# endif + +/* + * Fixed-point format: 0xABBBBBBB + * A == whole part (sign + 3 bits) + * B == fractional part (28 bits) + * + * Values are signed two's complement, so the effective range is: + * 0x80000000 to 0x7fffffff + * -8.0 to +7.9999999962747097015380859375 + * + * The smallest representable value is: + * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9) + * + * 28 bits of fractional accuracy represent about + * 8.6 digits of decimal accuracy. + * + * Fixed-point numbers can be added or subtracted as normal + * integers, but multiplication requires shifting the 64-bit result + * from 56 fractional bits back to 28 (and rounding.) + * + * Changing the definition of MAD_F_FRACBITS is only partially + * supported, and must be done with care. + */ + +# define MAD_F_FRACBITS 28 + +# if MAD_F_FRACBITS == 28 +# define MAD_F(x) ((mad_fixed_t) (x##L)) +# else +# if MAD_F_FRACBITS < 28 +# warning "MAD_F_FRACBITS < 28" +# define MAD_F(x) ((mad_fixed_t) \ + (((x##L) + \ + (1L << (28 - MAD_F_FRACBITS - 1))) >> \ + (28 - MAD_F_FRACBITS))) +# elif MAD_F_FRACBITS > 28 +# error "MAD_F_FRACBITS > 28 not currently supported" +# define MAD_F(x) ((mad_fixed_t) \ + ((x##L) << (MAD_F_FRACBITS - 28))) +# endif +# endif + +# define MAD_F_MIN ((mad_fixed_t) -0x80000000L) +# define MAD_F_MAX ((mad_fixed_t) +0x7fffffffL) + +# define MAD_F_ONE MAD_F(0x10000000) + +# define mad_f_tofixed(x) ((mad_fixed_t) \ + ((x) * (double) (1L << MAD_F_FRACBITS) + 0.5)) +# define mad_f_todouble(x) ((double) \ + ((x) / (double) (1L << MAD_F_FRACBITS))) + +# define mad_f_intpart(x) ((x) >> MAD_F_FRACBITS) +# define mad_f_fracpart(x) ((x) & ((1L << MAD_F_FRACBITS) - 1)) + /* (x should be positive) */ + +# define mad_f_fromint(x) ((x) << MAD_F_FRACBITS) + +# define mad_f_add(x, y) ((x) + (y)) +# define mad_f_sub(x, y) ((x) - (y)) + +# if defined(FPM_64BIT) + +/* + * This version should be the most accurate if 64-bit (long long) types are + * supported by the compiler, although it may not be the most efficient. + */ +# if defined(OPT_ACCURACY) +# define mad_f_mul(x, y) \ + ((mad_fixed_t) \ + ((((signed long long) (x) * (y)) + \ + (1L << (MAD_F_SCALEBITS - 1))) >> MAD_F_SCALEBITS)) +# else +# define mad_f_mul(x, y) \ + ((mad_fixed_t) (((signed long long) (x) * (y)) >> MAD_F_SCALEBITS)) +# endif + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- Intel --------------------------------------------------------------- */ + +# elif defined(FPM_INTEL) + +/* + * This Intel version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("imull %3" \ + : "=a" (lo), "=d" (hi) \ + : "%a" (x), "rm" (y) \ + : "cc") + +# if defined(OPT_ACCURACY) +/* + * This gives best accuracy but is not very fast. + */ +# define MAD_F_MLA(hi, lo, x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + asm ("addl %2,%0\n\t" \ + "adcl %3,%1" \ + : "=rm" (lo), "=rm" (hi) \ + : "r" (__lo), "r" (__hi), "0" (lo), "1" (hi) \ + : "cc"); \ + }) +# endif /* OPT_ACCURACY */ + +# if defined(OPT_ACCURACY) +/* + * Surprisingly, this is faster than SHRD followed by ADC. + */ +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed64hi_t __hi_; \ + mad_fixed64lo_t __lo_; \ + mad_fixed_t __result; \ + asm ("addl %4,%2\n\t" \ + "adcl %5,%3" \ + : "=rm" (__lo_), "=rm" (__hi_) \ + : "0" (lo), "1" (hi), \ + "ir" (1L << (MAD_F_SCALEBITS - 1)), "ir" (0) \ + : "cc"); \ + asm ("shrdl %3,%2,%1" \ + : "=rm" (__result) \ + : "0" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# else +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("shrdl %3,%2,%1" \ + : "=rm" (__result) \ + : "0" (lo), "r" (hi), "I" (MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# endif /* OPT_ACCURACY */ + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- ARM ----------------------------------------------------------------- */ + +# elif defined(FPM_ARM) + +/* + * This ARM V4 version is as accurate as FPM_64BIT but much faster. The + * least significant bit is properly rounded at no CPU cycle cost! + */ +# if 1 +/* + * There's a bug somewhere, possibly in the compiler, that sometimes makes + * this necessary instead of the default implementation via MAD_F_MLX and + * mad_f_scale64. It may be related to the use (or lack) of + * -finline-functions and/or -fstrength-reduce. + * + * This is also apparently faster than MAD_F_MLX/mad_f_scale64. + */ +# define mad_f_mul(x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + mad_fixed_t __result; \ + asm ("smull %0, %1, %3, %4\n\t" \ + "movs %0, %0, lsr %5\n\t" \ + "adc %2, %0, %1, lsl %6" \ + : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \ + : "%r" (x), "r" (y), \ + "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# endif + +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("smull %0, %1, %2, %3" \ + : "=&r" (lo), "=&r" (hi) \ + : "%r" (x), "r" (y)) + +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("smlal %0, %1, %2, %3" \ + : "+r" (lo), "+r" (hi) \ + : "%r" (x), "r" (y)) + +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("movs %0, %1, lsr %3\n\t" \ + "adc %0, %0, %2, lsl %4" \ + : "=r" (__result) \ + : "r" (lo), "r" (hi), \ + "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- MIPS ---------------------------------------------------------------- */ + +# elif defined(FPM_MIPS) + +/* + * This MIPS version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("mult %2,%3" \ + : "=l" (lo), "=h" (hi) \ + : "%r" (x), "r" (y)) + +# if defined(HAVE_MADD_ASM) +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("madd %2,%3" \ + : "+l" (lo), "+h" (hi) \ + : "%r" (x), "r" (y)) +# elif defined(HAVE_MADD16_ASM) +/* + * This loses significant accuracy due to the 16-bit integer limit in the + * multiply/accumulate instruction. + */ +# define MAD_F_ML0(hi, lo, x, y) \ + asm ("mult %2,%3" \ + : "=l" (lo), "=h" (hi) \ + : "%r" ((x) >> 12), "r" ((y) >> 16)) +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("madd16 %2,%3" \ + : "+l" (lo), "+h" (hi) \ + : "%r" ((x) >> 12), "r" ((y) >> 16)) +# define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo)) +# endif + +# if defined(OPT_SPEED) +# define mad_f_scale64(hi, lo) \ + ((mad_fixed_t) ((hi) << (32 - MAD_F_SCALEBITS))) +# define MAD_F_SCALEBITS MAD_F_FRACBITS +# endif + +/* --- SPARC --------------------------------------------------------------- */ + +# elif defined(FPM_SPARC) + +/* + * This SPARC V8 version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("smul %2, %3, %0\n\t" \ + "rd %%y, %1" \ + : "=r" (lo), "=r" (hi) \ + : "%r" (x), "rI" (y)) + +/* --- PowerPC ------------------------------------------------------------- */ + +# elif defined(FPM_PPC) + +/* + * This PowerPC version is tuned for the 4xx embedded processors. It is + * effectively a tuned version of FPM_64BIT. It is a little faster and just + * as accurate. The disposition of the least significant bit depends on + * OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("mulhw %1, %2, %3\n\t" \ + "mullw %0, %2, %3" \ + : "=&r" (lo), "=&r" (hi) \ + : "%r" (x), "r" (y)) + +# define MAD_F_MLA(hi, lo, x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + asm ("addc %0, %2, %3\n\t" \ + "adde %1, %4, %5" \ + : "=r" (lo), "=r" (hi) \ + : "%r" (__lo), "0" (lo), "%r" (__hi), "1" (hi)); \ + }) + +# if defined(OPT_ACCURACY) +/* + * This is accurate and ~2 - 2.5 times slower than the unrounded version. + * + * The __volatile__ improves the generated code by another 5% (fewer spills + * to memory); eventually they should be removed. + */ +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + mad_fixed64hi_t __hi_; \ + mad_fixed64lo_t __lo_; \ + asm __volatile__ ("addc %0, %2, %4\n\t" \ + "addze %1, %3" \ + : "=r" (__lo_), "=r" (__hi_) \ + : "r" (lo), "r" (hi), "r" (1 << (MAD_F_SCALEBITS - 1))); \ + asm __volatile__ ("rlwinm %0, %2,32-%3,0,%3-1\n\t" \ + "rlwimi %0, %1,32-%3,%3,31" \ + : "=&r" (__result) \ + : "r" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS)); \ + __result; \ + }) +# else +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("rlwinm %0, %2,32-%3,0,%3-1\n\t" \ + "rlwimi %0, %1,32-%3,%3,31" \ + : "=r" (__result) \ + : "r" (lo), "r" (hi), "I" (MAD_F_SCALEBITS)); \ + __result; \ + }) +# endif /* OPT_ACCURACY */ + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- Default ------------------------------------------------------------- */ + +# elif defined(FPM_DEFAULT) + +/* + * This version is the most portable but it loses significant accuracy. + * Furthermore, accuracy is biased against the second argument, so care + * should be taken when ordering operands. + * + * The scale factors are constant as this is not used with SSO. + * + * Pre-rounding is required to stay within the limits of compliance. + */ +# define mad_f_mul(x, y) ((((x) + (1L << 11)) >> 12) * \ + (((y) + (1L << 15)) >> 16)) + +/* ------------------------------------------------------------------------- */ + +# else +# error "no FPM selected" +# endif + +/* default implementations */ + +# if !defined(mad_f_mul) +# define mad_f_mul(x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + mad_f_scale64(__hi, __lo); \ + }) +# endif + +# if !defined(MAD_F_MLA) +# define MAD_F_ML0(hi, lo, x, y) ((lo) = mad_f_mul((x), (y))) +# define MAD_F_MLA(hi, lo, x, y) ((lo) += mad_f_mul((x), (y))) +# define MAD_F_MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) +# endif + +# if !defined(MAD_F_ML0) +# define MAD_F_ML0(hi, lo, x, y) MAD_F_MLX((hi), (lo), (x), (y)) +# endif + +# if !defined(MAD_F_MLZ) +# define MAD_F_MLZ(hi, lo) mad_f_scale64((hi), (lo)) +# endif + +# if !defined(mad_f_scale64) +# if defined(OPT_ACCURACY) +# define mad_f_scale64(hi, lo) \ + ((((mad_fixed_t) \ + (((hi) << (32 - (MAD_F_SCALEBITS - 1))) | \ + ((lo) >> (MAD_F_SCALEBITS - 1)))) + 1) >> 1) +# else +# define mad_f_scale64(hi, lo) \ + ((mad_fixed_t) \ + (((hi) << (32 - MAD_F_SCALEBITS)) | \ + ((lo) >> MAD_F_SCALEBITS))) +# endif +# define MAD_F_SCALEBITS MAD_F_FRACBITS +# endif + +/* miscellaneous C routines */ + +mad_fixed_t mad_f_abs(mad_fixed_t); + +# endif diff --git a/core/multimedia/opieplayer/libmad/frame.c b/core/multimedia/opieplayer/libmad/frame.c new file mode 100644 index 0000000..4ebb80c --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/frame.c @@ -0,0 +1,499 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifdef HAVE_CONFIG_H +# include "libmad_config.h" +# endif + +# include "libmad_global.h" + +# include + +# include "bit.h" +# include "stream.h" +# include "frame.h" +# include "timer.h" +# include "layer12.h" +# include "layer3.h" + +static +unsigned long const bitrate_table[5][15] = { + /* MPEG-1 */ + { 0, 32000, 64000, 96000, 128000, 160000, 192000, 224000, /* Layer I */ + 256000, 288000, 320000, 352000, 384000, 416000, 448000 }, + { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer II */ + 128000, 160000, 192000, 224000, 256000, 320000, 384000 }, + { 0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, /* Layer III */ + 112000, 128000, 160000, 192000, 224000, 256000, 320000 }, + + /* MPEG-2 LSF */ + { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer I */ + 128000, 144000, 160000, 176000, 192000, 224000, 256000 }, + { 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, /* Layers */ + 64000, 80000, 96000, 112000, 128000, 144000, 160000 } /* II & III */ +}; + +static +unsigned int const samplerate_table[3] = { 44100, 48000, 32000 }; + +static +int (*const decoder_table[3])(struct mad_stream *, struct mad_frame *) = { + mad_layer_I, + mad_layer_II, + mad_layer_III +}; + +/* + * NAME: header->init() + * DESCRIPTION: initialize header struct + */ +void mad_header_init(struct mad_header *header) +{ + header->layer = 0; + header->mode = 0; + header->mode_extension = 0; + header->emphasis = 0; + + header->bitrate = 0; + header->samplerate = 0; + + header->crc_check = 0; + header->crc_target = 0; + + header->flags = 0; + header->private_bits = 0; + + header->duration = mad_timer_zero; +} + +/* + * NAME: frame->init() + * DESCRIPTION: initialize frame struct + */ +void mad_frame_init(struct mad_frame *frame) +{ + mad_header_init(&frame->header); + + frame->options = 0; + + frame->overlap = 0; + mad_frame_mute(frame); +} + +/* + * NAME: frame->finish() + * DESCRIPTION: deallocate any dynamic memory associated with frame + */ +void mad_frame_finish(struct mad_frame *frame) +{ + mad_header_finish(&frame->header); + + if (frame->overlap) { + free(frame->overlap); + frame->overlap = 0; + } +} + +/* + * NAME: decode_header() + * DESCRIPTION: read header data and following CRC word + */ +static +int decode_header(struct mad_header *header, struct mad_stream *stream) +{ + unsigned int index; + + header->flags = 0; + header->private_bits = 0; + + /* header() */ + + /* syncword */ + mad_bit_skip(&stream->ptr, 11); + + /* MPEG 2.5 indicator (really part of syncword) */ + if (mad_bit_read(&stream->ptr, 1) == 0) + header->flags |= MAD_FLAG_MPEG_2_5_EXT; + + /* ID */ + if (mad_bit_read(&stream->ptr, 1) == 0) + header->flags |= MAD_FLAG_LSF_EXT; + else if (header->flags & MAD_FLAG_MPEG_2_5_EXT) { + stream->error = MAD_ERROR_LOSTSYNC; + return -1; + } + + /* layer */ + header->layer = 4 - mad_bit_read(&stream->ptr, 2); + + if (header->layer == 4) { + stream->error = MAD_ERROR_BADLAYER; + return -1; + } + + /* protection_bit */ + if (mad_bit_read(&stream->ptr, 1) == 0) { + header->flags |= MAD_FLAG_PROTECTION; + header->crc_check = mad_bit_crc(stream->ptr, 16, 0xffff); + } + + /* bitrate_index */ + index = mad_bit_read(&stream->ptr, 4); + + if (index == 15) { + stream->error = MAD_ERROR_BADBITRATE; + return -1; + } + + if (header->flags & MAD_FLAG_LSF_EXT) + header->bitrate = bitrate_table[3 + (header->layer >> 1)][index]; + else + header->bitrate = bitrate_table[header->layer - 1][index]; + + /* sampling_frequency */ + index = mad_bit_read(&stream->ptr, 2); + + if (index == 3) { + stream->error = MAD_ERROR_BADSAMPLERATE; + return -1; + } + + header->samplerate = samplerate_table[index]; + + if (header->flags & MAD_FLAG_LSF_EXT) { + header->samplerate /= 2; + + if (header->flags & MAD_FLAG_MPEG_2_5_EXT) + header->samplerate /= 2; + } + + /* padding_bit */ + if (mad_bit_read(&stream->ptr, 1)) + header->flags |= MAD_FLAG_PADDING; + + /* private_bit */ + if (mad_bit_read(&stream->ptr, 1)) + header->private_bits |= MAD_PRIVATE_HEADER; + + /* mode */ + header->mode = 3 - mad_bit_read(&stream->ptr, 2); + + /* mode_extension */ + header->mode_extension = mad_bit_read(&stream->ptr, 2); + + /* copyright */ + if (mad_bit_read(&stream->ptr, 1)) + header->flags |= MAD_FLAG_COPYRIGHT; + + /* original/copy */ + if (mad_bit_read(&stream->ptr, 1)) + header->flags |= MAD_FLAG_ORIGINAL; + + /* emphasis */ + header->emphasis = mad_bit_read(&stream->ptr, 2); + + if (header->emphasis == 2) { + stream->error = MAD_ERROR_BADEMPHASIS; + return -1; + } + + /* error_check() */ + + /* crc_check */ + if (header->flags & MAD_FLAG_PROTECTION) + header->crc_target = mad_bit_read(&stream->ptr, 16); + + return 0; +} + +/* + * NAME: free_bitrate() + * DESCRIPTION: attempt to discover the bitstream's free bitrate + */ +static +int free_bitrate(struct mad_stream *stream, struct mad_header const *header) +{ + struct mad_bitptr keep_ptr; + unsigned long rate = 0; + unsigned int pad_slot, slots_per_frame; + unsigned char const *ptr = 0; + + keep_ptr = stream->ptr; + + pad_slot = (header->flags & MAD_FLAG_PADDING) ? 1 : 0; + slots_per_frame = (header->layer == MAD_LAYER_III && + (header->flags & MAD_FLAG_LSF_EXT)) ? 72 : 144; + + while (mad_stream_sync(stream) == 0) { + struct mad_stream peek_stream; + struct mad_header peek_header; + + peek_stream = *stream; + peek_header = *header; + + if (decode_header(&peek_header, &peek_stream) == 0 && + peek_header.layer == header->layer && + peek_header.samplerate == header->samplerate) { + unsigned int N; + + ptr = mad_bit_nextbyte(&stream->ptr); + + N = ptr - stream->this_frame; + + if (header->layer == MAD_LAYER_I) { + rate = (unsigned long) header->samplerate * + (N - 4 * pad_slot + 4) / 48 / 1000; + } + else { + rate = (unsigned long) header->samplerate * + (N - pad_slot + 1) / slots_per_frame / 1000; + } + + if (rate >= 8) + break; + } + + mad_bit_skip(&stream->ptr, 8); + } + + stream->ptr = keep_ptr; + + if (rate < 8 || (header->layer == MAD_LAYER_III && rate > 640)) { + stream->error = MAD_ERROR_LOSTSYNC; + return -1; + } + + stream->freerate = rate * 1000; + +# if 0 && defined(DEBUG) + fprintf(stderr, "free bitrate == %lu\n", stream->freerate); +# endif + + return 0; +} + +/* + * NAME: header->decode() + * DESCRIPTION: read the next frame header from the stream + */ +int mad_header_decode(struct mad_header *header, struct mad_stream *stream) +{ + register unsigned char const *ptr, *end; + unsigned int pad_slot, N; + + ptr = stream->next_frame; + end = stream->bufend; + + if (ptr == 0) { + stream->error = MAD_ERROR_BUFPTR; + goto fail; + } + + /* stream skip */ + if (stream->skiplen) { + if (!stream->sync) + ptr = stream->this_frame; + + if (end - ptr < stream->skiplen) { + stream->skiplen -= end - ptr; + stream->next_frame = end; + + stream->error = MAD_ERROR_BUFLEN; + goto fail; + } + + ptr += stream->skiplen; + stream->skiplen = 0; + + stream->sync = 1; + } + + sync: + /* synchronize */ + if (stream->sync) { + if (end - ptr < MAD_BUFFER_GUARD) { + stream->next_frame = ptr; + + stream->error = MAD_ERROR_BUFLEN; + goto fail; + } + else if (!(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) { + /* mark point where frame sync word was expected */ + stream->this_frame = ptr; + stream->next_frame = ptr + 1; + + stream->error = MAD_ERROR_LOSTSYNC; + goto fail; + } + } + else { + mad_bit_init(&stream->ptr, ptr); + + if (mad_stream_sync(stream) == -1) { + if (end - stream->next_frame >= MAD_BUFFER_GUARD) + stream->next_frame = end - MAD_BUFFER_GUARD; + + stream->error = MAD_ERROR_BUFLEN; + goto fail; + } + + ptr = mad_bit_nextbyte(&stream->ptr); + } + + /* begin processing */ + stream->this_frame = ptr; + stream->next_frame = ptr + 1; /* possibly bogus sync word */ + + mad_bit_init(&stream->ptr, stream->this_frame); + + if (decode_header(header, stream) == -1) + goto fail; + + /* calculate frame duration */ + mad_timer_set(&header->duration, 0, + 32 * MAD_NSBSAMPLES(header), header->samplerate); + + /* calculate free bit rate */ + if (header->bitrate == 0) { + if ((!stream->sync || !stream->freerate) && + free_bitrate(stream, header) == -1) + goto fail; + + header->bitrate = stream->freerate; + header->flags |= MAD_FLAG_FREEFORMAT; + } + + /* calculate beginning of next frame */ + pad_slot = (header->flags & MAD_FLAG_PADDING) ? 1 : 0; + + if (header->layer == MAD_LAYER_I) + N = ((12 * header->bitrate / header->samplerate) + pad_slot) * 4; + else { + unsigned int slots_per_frame; + + slots_per_frame = (header->layer == MAD_LAYER_III && + (header->flags & MAD_FLAG_LSF_EXT)) ? 72 : 144; + + N = (slots_per_frame * header->bitrate / header->samplerate) + pad_slot; + } + + /* verify there is enough data left in buffer to decode this frame */ + if (N + MAD_BUFFER_GUARD > end - stream->this_frame) { + stream->next_frame = stream->this_frame; + + stream->error = MAD_ERROR_BUFLEN; + goto fail; + } + + stream->next_frame = stream->this_frame + N; + + if (!stream->sync) { + /* check that a valid frame header follows this frame */ + + ptr = stream->next_frame; + if (!(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) { + ptr = stream->next_frame = stream->this_frame + 1; + goto sync; + } + + stream->sync = 1; + } + + header->flags |= MAD_FLAG_INCOMPLETE; + + return 0; + + fail: + stream->sync = 0; + + return -1; +} + +/* + * NAME: frame->decode() + * DESCRIPTION: decode a single frame from a bitstream + */ +int mad_frame_decode(struct mad_frame *frame, struct mad_stream *stream) +{ + frame->options = stream->options; + + /* header() */ + /* error_check() */ + + if (!(frame->header.flags & MAD_FLAG_INCOMPLETE) && + mad_header_decode(&frame->header, stream) == -1) + goto fail; + + /* audio_data() */ + + frame->header.flags &= ~MAD_FLAG_INCOMPLETE; + + if (decoder_table[frame->header.layer - 1](stream, frame) == -1) { + if (!MAD_RECOVERABLE(stream->error)) + stream->next_frame = stream->this_frame; + + goto fail; + } + + /* ancillary_data() */ + + if (frame->header.layer != MAD_LAYER_III) { + struct mad_bitptr next_frame; + + mad_bit_init(&next_frame, stream->next_frame); + + stream->anc_ptr = stream->ptr; + stream->anc_bitlen = mad_bit_length(&stream->ptr, &next_frame); + + mad_bit_finish(&next_frame); + } + + return 0; + + fail: + stream->anc_bitlen = 0; + return -1; +} + +/* + * NAME: frame->mute() + * DESCRIPTION: zero all subband values so the frame becomes silent + */ +void mad_frame_mute(struct mad_frame *frame) +{ + unsigned int s, sb; + + for (s = 0; s < 36; ++s) { + for (sb = 0; sb < 32; ++sb) { + frame->sbsample[0][s][sb] = + frame->sbsample[1][s][sb] = 0; + } + } + + if (frame->overlap) { + for (s = 0; s < 18; ++s) { + for (sb = 0; sb < 32; ++sb) { + (*frame->overlap)[0][sb][s] = + (*frame->overlap)[1][sb][s] = 0; + } + } + } +} diff --git a/core/multimedia/opieplayer/libmad/frame.h b/core/multimedia/opieplayer/libmad/frame.h new file mode 100644 index 0000000..e88d0c8 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/frame.h @@ -0,0 +1,115 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_FRAME_H +# define LIBMAD_FRAME_H + +# include "fixed.h" +# include "timer.h" +# include "stream.h" + +enum mad_layer { + MAD_LAYER_I = 1, /* Layer I */ + MAD_LAYER_II = 2, /* Layer II */ + MAD_LAYER_III = 3 /* Layer III */ +}; + +enum mad_mode { + MAD_MODE_SINGLE_CHANNEL = 0, /* single channel */ + MAD_MODE_DUAL_CHANNEL = 1, /* dual channel */ + MAD_MODE_JOINT_STEREO = 2, /* joint (MS/intensity) stereo */ + MAD_MODE_STEREO = 3 /* normal LR stereo */ +}; + +enum mad_emphasis { + MAD_EMPHASIS_NONE = 0, /* no emphasis */ + MAD_EMPHASIS_50_15_US = 1, /* 50/15 microseconds emphasis */ + MAD_EMPHASIS_CCITT_J_17 = 3 /* CCITT J.17 emphasis */ +}; + +struct mad_frame { + struct mad_header { + enum mad_layer layer; /* audio layer (1, 2, or 3) */ + enum mad_mode mode; /* channel mode (see above) */ + int mode_extension; /* additional mode info */ + enum mad_emphasis emphasis; /* de-emphasis to use (see above) */ + + unsigned long bitrate; /* stream bitrate (bps) */ + unsigned int samplerate; /* sampling frequency (Hz) */ + + unsigned short crc_check; /* frame CRC accumulator */ + unsigned short crc_target; /* final target CRC checksum */ + + int flags; /* flags (see below) */ + int private_bits; /* private bits (see below) */ + + mad_timer_t duration; /* audio playing time of frame */ + } header; + + int options; /* decoding options (from stream) */ + + mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */ + mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */ +}; + +# define MAD_NCHANNELS(header) ((header)->mode ? 2 : 1) +# define MAD_NSBSAMPLES(header) \ + ((header)->layer == MAD_LAYER_I ? 12 : \ + (((header)->layer == MAD_LAYER_III && \ + ((header)->flags & MAD_FLAG_LSF_EXT)) ? 18 : 36)) + +enum { + MAD_FLAG_NPRIVATE_III = 0x0007, /* number of Layer III private bits */ + MAD_FLAG_INCOMPLETE = 0x0008, /* header but not data is decoded */ + + MAD_FLAG_PROTECTION = 0x0010, /* frame has CRC protection */ + MAD_FLAG_COPYRIGHT = 0x0020, /* frame is copyright */ + MAD_FLAG_ORIGINAL = 0x0040, /* frame is original (else copy) */ + MAD_FLAG_PADDING = 0x0080, /* frame has additional slot */ + + MAD_FLAG_I_STEREO = 0x0100, /* uses intensity joint stereo */ + MAD_FLAG_MS_STEREO = 0x0200, /* uses middle/side joint stereo */ + MAD_FLAG_FREEFORMAT = 0x0400, /* uses free format bitrate */ + + MAD_FLAG_LSF_EXT = 0x1000, /* lower sampling freq. extension */ + MAD_FLAG_MC_EXT = 0x2000, /* multichannel audio extension */ + MAD_FLAG_MPEG_2_5_EXT = 0x4000 /* MPEG 2.5 (unofficial) extension */ +}; + +enum { + MAD_PRIVATE_HEADER = 0x0100, /* header private bit */ + MAD_PRIVATE_III = 0x001f /* Layer III private bits (up to 5) */ +}; + +void mad_header_init(struct mad_header *); + +# define mad_header_finish(header) /* nothing */ + +int mad_header_decode(struct mad_header *, struct mad_stream *); + +void mad_frame_init(struct mad_frame *); +void mad_frame_finish(struct mad_frame *); + +int mad_frame_decode(struct mad_frame *, struct mad_stream *); + +void mad_frame_mute(struct mad_frame *); + +# endif diff --git a/core/multimedia/opieplayer/libmad/huffman.c b/core/multimedia/opieplayer/libmad/huffman.c new file mode 100644 index 0000000..8ec9499 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/huffman.c @@ -0,0 +1,3087 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifdef HAVE_CONFIG_H +# include "libmad_config.h" +# endif + +# include "libmad_global.h" + +# include "huffman.h" + +/* + * These are the Huffman code words for Layer III. + * The data for these tables are derived from Table B.7 of ISO/IEC 11172-3. + * + * These tables support decoding up to 4 Huffman code bits at a time. + */ + +# define V(v, w, x, y, hlen) { { 1, hlen, v, w, x, y } } +# define PTR(offs, bits) { ptr: { 0, bits, offs } } + +static +union huffquad const hufftabA[] = { + /* 0000 */ PTR(16, 2), + /* 0001 */ PTR(20, 2), + /* 0010 */ PTR(24, 1), + /* 0011 */ PTR(26, 1), + /* 0100 */ V(0, 0, 1, 0, 4), + /* 0101 */ V(0, 0, 0, 1, 4), + /* 0110 */ V(0, 1, 0, 0, 4), + /* 0111 */ V(1, 0, 0, 0, 4), + /* 1000 */ V(0, 0, 0, 0, 1), + /* 1001 */ V(0, 0, 0, 0, 1), + /* 1010 */ V(0, 0, 0, 0, 1), + /* 1011 */ V(0, 0, 0, 0, 1), + /* 1100 */ V(0, 0, 0, 0, 1), + /* 1101 */ V(0, 0, 0, 0, 1), + /* 1110 */ V(0, 0, 0, 0, 1), + /* 1111 */ V(0, 0, 0, 0, 1), + + /* 0000 ... */ + /* 00 */ V(1, 0, 1, 1, 2), /* 16 */ + /* 01 */ V(1, 1, 1, 1, 2), + /* 10 */ V(1, 1, 0, 1, 2), + /* 11 */ V(1, 1, 1, 0, 2), + + /* 0001 ... */ + /* 00 */ V(0, 1, 1, 1, 2), /* 20 */ + /* 01 */ V(0, 1, 0, 1, 2), + /* 10 */ V(1, 0, 0, 1, 1), + /* 11 */ V(1, 0, 0, 1, 1), + + /* 0010 ... */ + /* 0 */ V(0, 1, 1, 0, 1), /* 24 */ + /* 1 */ V(0, 0, 1, 1, 1), + + /* 0011 ... */ + /* 0 */ V(1, 0, 1, 0, 1), /* 26 */ + /* 1 */ V(1, 1, 0, 0, 1) +}; + +static +union huffquad const hufftabB[] = { + /* 0000 */ V(1, 1, 1, 1, 4), + /* 0001 */ V(1, 1, 1, 0, 4), + /* 0010 */ V(1, 1, 0, 1, 4), + /* 0011 */ V(1, 1, 0, 0, 4), + /* 0100 */ V(1, 0, 1, 1, 4), + /* 0101 */ V(1, 0, 1, 0, 4), + /* 0110 */ V(1, 0, 0, 1, 4), + /* 0111 */ V(1, 0, 0, 0, 4), + /* 1000 */ V(0, 1, 1, 1, 4), + /* 1001 */ V(0, 1, 1, 0, 4), + /* 1010 */ V(0, 1, 0, 1, 4), + /* 1011 */ V(0, 1, 0, 0, 4), + /* 1100 */ V(0, 0, 1, 1, 4), + /* 1101 */ V(0, 0, 1, 0, 4), + /* 1110 */ V(0, 0, 0, 1, 4), + /* 1111 */ V(0, 0, 0, 0, 4) +}; + +# undef V +# undef PTR + +# define V(x, y, hlen) { { 1, hlen, x, y } } +# define PTR(offs, bits) { ptr: { 0, bits, offs } } + +static +union huffpair const hufftab0[] = { + /* */ V(0, 0, 0) +}; + +static +union huffpair const hufftab1[] = { + /* 000 */ V(1, 1, 3), + /* 001 */ V(0, 1, 3), + /* 010 */ V(1, 0, 2), + /* 011 */ V(1, 0, 2), + /* 100 */ V(0, 0, 1), + /* 101 */ V(0, 0, 1), + /* 110 */ V(0, 0, 1), + /* 111 */ V(0, 0, 1) +}; + +static +union huffpair const hufftab2[] = { + /* 000 */ PTR(8, 3), + /* 001 */ V(1, 1, 3), + /* 010 */ V(0, 1, 3), + /* 011 */ V(1, 0, 3), + /* 100 */ V(0, 0, 1), + /* 101 */ V(0, 0, 1), + /* 110 */ V(0, 0, 1), + /* 111 */ V(0, 0, 1), + + /* 000 ... */ + /* 000 */ V(2, 2, 3), /* 8 */ + /* 001 */ V(0, 2, 3), + /* 010 */ V(1, 2, 2), + /* 011 */ V(1, 2, 2), + /* 100 */ V(2, 1, 2), + /* 101 */ V(2, 1, 2), + /* 110 */ V(2, 0, 2), + /* 111 */ V(2, 0, 2) +}; + +static +union huffpair const hufftab3[] = { + /* 000 */ PTR(8, 3), + /* 001 */ V(1, 0, 3), + /* 010 */ V(1, 1, 2), + /* 011 */ V(1, 1, 2), + /* 100 */ V(0, 1, 2), + /* 101 */ V(0, 1, 2), + /* 110 */ V(0, 0, 2), + /* 111 */ V(0, 0, 2), + + /* 000 ... */ + /* 000 */ V(2, 2, 3), /* 8 */ + /* 001 */ V(0, 2, 3), + /* 010 */ V(1, 2, 2), + /* 011 */ V(1, 2, 2), + /* 100 */ V(2, 1, 2), + /* 101 */ V(2, 1, 2), + /* 110 */ V(2, 0, 2), + /* 111 */ V(2, 0, 2) +}; + +static +union huffpair const hufftab5[] = { + /* 000 */ PTR(8, 4), + /* 001 */ V(1, 1, 3), + /* 010 */ V(0, 1, 3), + /* 011 */ V(1, 0, 3), + /* 100 */ V(0, 0, 1), + /* 101 */ V(0, 0, 1), + /* 110 */ V(0, 0, 1), + /* 111 */ V(0, 0, 1), + + /* 000 ... */ + /* 0000 */ PTR(24, 1), /* 8 */ + /* 0001 */ V(3, 2, 4), + /* 0010 */ V(3, 1, 3), + /* 0011 */ V(3, 1, 3), + /* 0100 */ V(1, 3, 4), + /* 0101 */ V(0, 3, 4), + /* 0110 */ V(3, 0, 4), + /* 0111 */ V(2, 2, 4), + /* 1000 */ V(1, 2, 3), + /* 1001 */ V(1, 2, 3), + /* 1010 */ V(2, 1, 3), + /* 1011 */ V(2, 1, 3), + /* 1100 */ V(0, 2, 3), + /* 1101 */ V(0, 2, 3), + /* 1110 */ V(2, 0, 3), + /* 1111 */ V(2, 0, 3), + + /* 000 0000 ... */ + /* 0 */ V(3, 3, 1), /* 24 */ + /* 1 */ V(2, 3, 1) +}; + +static +union huffpair const hufftab6[] = { + /* 0000 */ PTR(16, 3), + /* 0001 */ PTR(24, 1), + /* 0010 */ PTR(26, 1), + /* 0011 */ V(1, 2, 4), + /* 0100 */ V(2, 1, 4), + /* 0101 */ V(2, 0, 4), + /* 0110 */ V(0, 1, 3), + /* 0111 */ V(0, 1, 3), + /* 1000 */ V(1, 1, 2), + /* 1001 */ V(1, 1, 2), + /* 1010 */ V(1, 1, 2), + /* 1011 */ V(1, 1, 2), + /* 1100 */ V(1, 0, 3), + /* 1101 */ V(1, 0, 3), + /* 1110 */ V(0, 0, 3), + /* 1111 */ V(0, 0, 3), + + /* 0000 ... */ + /* 000 */ V(3, 3, 3), /* 16 */ + /* 001 */ V(0, 3, 3), + /* 010 */ V(2, 3, 2), + /* 011 */ V(2, 3, 2), + /* 100 */ V(3, 2, 2), + /* 101 */ V(3, 2, 2), + /* 110 */ V(3, 0, 2), + /* 111 */ V(3, 0, 2), + + /* 0001 ... */ + /* 0 */ V(1, 3, 1), /* 24 */ + /* 1 */ V(3, 1, 1), + + /* 0010 ... */ + /* 0 */ V(2, 2, 1), /* 26 */ + /* 1 */ V(0, 2, 1) +}; + +static +union huffpair const hufftab7[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 2), + /* 0011 */ V(1, 1, 4), + /* 0100 */ V(0, 1, 3), + /* 0101 */ V(0, 1, 3), + /* 0110 */ V(1, 0, 3), + /* 0111 */ V(1, 0, 3), + /* 1000 */ V(0, 0, 1), + /* 1001 */ V(0, 0, 1), + /* 1010 */ V(0, 0, 1), + /* 1011 */ V(0, 0, 1), + /* 1100 */ V(0, 0, 1), + /* 1101 */ V(0, 0, 1), + /* 1110 */ V(0, 0, 1), + /* 1111 */ V(0, 0, 1), + + /* 0000 ... */ + /* 0000 */ PTR(52, 2), /* 16 */ + /* 0001 */ PTR(56, 1), + /* 0010 */ PTR(58, 1), + /* 0011 */ V(1, 5, 4), + /* 0100 */ V(5, 1, 4), + /* 0101 */ PTR(60, 1), + /* 0110 */ V(5, 0, 4), + /* 0111 */ PTR(62, 1), + /* 1000 */ V(2, 4, 4), + /* 1001 */ V(4, 2, 4), + /* 1010 */ V(1, 4, 3), + /* 1011 */ V(1, 4, 3), + /* 1100 */ V(4, 1, 3), + /* 1101 */ V(4, 1, 3), + /* 1110 */ V(4, 0, 3), + /* 1111 */ V(4, 0, 3), + + /* 0001 ... */ + /* 0000 */ V(0, 4, 4), /* 32 */ + /* 0001 */ V(2, 3, 4), + /* 0010 */ V(3, 2, 4), + /* 0011 */ V(0, 3, 4), + /* 0100 */ V(1, 3, 3), + /* 0101 */ V(1, 3, 3), + /* 0110 */ V(3, 1, 3), + /* 0111 */ V(3, 1, 3), + /* 1000 */ V(3, 0, 3), + /* 1001 */ V(3, 0, 3), + /* 1010 */ V(2, 2, 3), + /* 1011 */ V(2, 2, 3), + /* 1100 */ V(1, 2, 2), + /* 1101 */ V(1, 2, 2), + /* 1110 */ V(1, 2, 2), + /* 1111 */ V(1, 2, 2), + + /* 0010 ... */ + /* 00 */ V(2, 1, 1), /* 48 */ + /* 01 */ V(2, 1, 1), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 00 */ V(5, 5, 2), /* 52 */ + /* 01 */ V(4, 5, 2), + /* 10 */ V(5, 4, 2), + /* 11 */ V(5, 3, 2), + + /* 0000 0001 ... */ + /* 0 */ V(3, 5, 1), /* 56 */ + /* 1 */ V(4, 4, 1), + + /* 0000 0010 ... */ + /* 0 */ V(2, 5, 1), /* 58 */ + /* 1 */ V(5, 2, 1), + + /* 0000 0101 ... */ + /* 0 */ V(0, 5, 1), /* 60 */ + /* 1 */ V(3, 4, 1), + + /* 0000 0111 ... */ + /* 0 */ V(4, 3, 1), /* 62 */ + /* 1 */ V(3, 3, 1) +}; + +# if 0 +/* this version saves 8 entries (16 bytes) at the expense of + an extra lookup in 4 out of 36 cases */ +static +union huffpair const hufftab8[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 2), + /* 0010 */ V(1, 2, 4), + /* 0011 */ V(2, 1, 4), + /* 0100 */ V(1, 1, 2), + /* 0101 */ V(1, 1, 2), + /* 0110 */ V(1, 1, 2), + /* 0111 */ V(1, 1, 2), + /* 1000 */ V(0, 1, 3), + /* 1001 */ V(0, 1, 3), + /* 1010 */ V(1, 0, 3), + /* 1011 */ V(1, 0, 3), + /* 1100 */ V(0, 0, 2), + /* 1101 */ V(0, 0, 2), + /* 1110 */ V(0, 0, 2), + /* 1111 */ V(0, 0, 2), + + /* 0000 ... */ + /* 0000 */ PTR(36, 3), /* 16 */ + /* 0001 */ PTR(44, 2), + /* 0010 */ PTR(48, 1), + /* 0011 */ V(1, 5, 4), + /* 0100 */ V(5, 1, 4), + /* 0101 */ PTR(50, 1), + /* 0110 */ PTR(52, 1), + /* 0111 */ V(2, 4, 4), + /* 1000 */ V(4, 2, 4), + /* 1001 */ V(1, 4, 4), + /* 1010 */ V(4, 1, 3), + /* 1011 */ V(4, 1, 3), + /* 1100 */ V(0, 4, 4), + /* 1101 */ V(4, 0, 4), + /* 1110 */ V(2, 3, 4), + /* 1111 */ V(3, 2, 4), + + /* 0001 ... */ + /* 00 */ PTR(54, 2), /* 32 */ + /* 01 */ V(2, 2, 2), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 000 */ V(5, 5, 3), /* 36 */ + /* 001 */ V(5, 4, 3), + /* 010 */ V(4, 5, 2), + /* 011 */ V(4, 5, 2), + /* 100 */ V(5, 3, 1), + /* 101 */ V(5, 3, 1), + /* 110 */ V(5, 3, 1), + /* 111 */ V(5, 3, 1), + + /* 0000 0001 ... */ + /* 00 */ V(3, 5, 2), /* 44 */ + /* 01 */ V(4, 4, 2), + /* 10 */ V(2, 5, 1), + /* 11 */ V(2, 5, 1), + + /* 0000 0010 ... */ + /* 0 */ V(5, 2, 1), /* 48 */ + /* 1 */ V(0, 5, 1), + + /* 0000 0101 ... */ + /* 0 */ V(3, 4, 1), /* 50 */ + /* 1 */ V(4, 3, 1), + + /* 0000 0110 ... */ + /* 0 */ V(5, 0, 1), /* 52 */ + /* 1 */ V(3, 3, 1), + + /* 0001 00 ... */ + /* 00 */ V(1, 3, 2), /* 54 */ + /* 01 */ V(3, 1, 2), + /* 10 */ V(0, 3, 2), + /* 11 */ V(3, 0, 2), +}; +# else +static +union huffpair const hufftab8[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ V(1, 2, 4), + /* 0011 */ V(2, 1, 4), + /* 0100 */ V(1, 1, 2), + /* 0101 */ V(1, 1, 2), + /* 0110 */ V(1, 1, 2), + /* 0111 */ V(1, 1, 2), + /* 1000 */ V(0, 1, 3), + /* 1001 */ V(0, 1, 3), + /* 1010 */ V(1, 0, 3), + /* 1011 */ V(1, 0, 3), + /* 1100 */ V(0, 0, 2), + /* 1101 */ V(0, 0, 2), + /* 1110 */ V(0, 0, 2), + /* 1111 */ V(0, 0, 2), + + /* 0000 ... */ + /* 0000 */ PTR(48, 3), /* 16 */ + /* 0001 */ PTR(56, 2), + /* 0010 */ PTR(60, 1), + /* 0011 */ V(1, 5, 4), + /* 0100 */ V(5, 1, 4), + /* 0101 */ PTR(62, 1), + /* 0110 */ PTR(64, 1), + /* 0111 */ V(2, 4, 4), + /* 1000 */ V(4, 2, 4), + /* 1001 */ V(1, 4, 4), + /* 1010 */ V(4, 1, 3), + /* 1011 */ V(4, 1, 3), + /* 1100 */ V(0, 4, 4), + /* 1101 */ V(4, 0, 4), + /* 1110 */ V(2, 3, 4), + /* 1111 */ V(3, 2, 4), + + /* 0001 ... */ + /* 0000 */ V(1, 3, 4), /* 32 */ + /* 0001 */ V(3, 1, 4), + /* 0010 */ V(0, 3, 4), + /* 0011 */ V(3, 0, 4), + /* 0100 */ V(2, 2, 2), + /* 0101 */ V(2, 2, 2), + /* 0110 */ V(2, 2, 2), + /* 0111 */ V(2, 2, 2), + /* 1000 */ V(0, 2, 2), + /* 1001 */ V(0, 2, 2), + /* 1010 */ V(0, 2, 2), + /* 1011 */ V(0, 2, 2), + /* 1100 */ V(2, 0, 2), + /* 1101 */ V(2, 0, 2), + /* 1110 */ V(2, 0, 2), + /* 1111 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 000 */ V(5, 5, 3), /* 48 */ + /* 001 */ V(5, 4, 3), + /* 010 */ V(4, 5, 2), + /* 011 */ V(4, 5, 2), + /* 100 */ V(5, 3, 1), + /* 101 */ V(5, 3, 1), + /* 110 */ V(5, 3, 1), + /* 111 */ V(5, 3, 1), + + /* 0000 0001 ... */ + /* 00 */ V(3, 5, 2), /* 56 */ + /* 01 */ V(4, 4, 2), + /* 10 */ V(2, 5, 1), + /* 11 */ V(2, 5, 1), + + /* 0000 0010 ... */ + /* 0 */ V(5, 2, 1), /* 60 */ + /* 1 */ V(0, 5, 1), + + /* 0000 0101 ... */ + /* 0 */ V(3, 4, 1), /* 62 */ + /* 1 */ V(4, 3, 1), + + /* 0000 0110 ... */ + /* 0 */ V(5, 0, 1), /* 64 */ + /* 1 */ V(3, 3, 1) +}; +# endif + +static +union huffpair const hufftab9[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 3), + /* 0010 */ PTR(40, 2), + /* 0011 */ PTR(44, 2), + /* 0100 */ PTR(48, 1), + /* 0101 */ V(1, 2, 4), + /* 0110 */ V(2, 1, 4), + /* 0111 */ V(2, 0, 4), + /* 1000 */ V(1, 1, 3), + /* 1001 */ V(1, 1, 3), + /* 1010 */ V(0, 1, 3), + /* 1011 */ V(0, 1, 3), + /* 1100 */ V(1, 0, 3), + /* 1101 */ V(1, 0, 3), + /* 1110 */ V(0, 0, 3), + /* 1111 */ V(0, 0, 3), + + /* 0000 ... */ + /* 0000 */ PTR(50, 1), /* 16 */ + /* 0001 */ V(3, 5, 4), + /* 0010 */ V(5, 3, 4), + /* 0011 */ PTR(52, 1), + /* 0100 */ V(4, 4, 4), + /* 0101 */ V(2, 5, 4), + /* 0110 */ V(5, 2, 4), + /* 0111 */ V(1, 5, 4), + /* 1000 */ V(5, 1, 3), + /* 1001 */ V(5, 1, 3), + /* 1010 */ V(3, 4, 3), + /* 1011 */ V(3, 4, 3), + /* 1100 */ V(4, 3, 3), + /* 1101 */ V(4, 3, 3), + /* 1110 */ V(5, 0, 4), + /* 1111 */ V(0, 4, 4), + + /* 0001 ... */ + /* 000 */ V(2, 4, 3), /* 32 */ + /* 001 */ V(4, 2, 3), + /* 010 */ V(3, 3, 3), + /* 011 */ V(4, 0, 3), + /* 100 */ V(1, 4, 2), + /* 101 */ V(1, 4, 2), + /* 110 */ V(4, 1, 2), + /* 111 */ V(4, 1, 2), + + /* 0010 ... */ + /* 00 */ V(2, 3, 2), /* 40 */ + /* 01 */ V(3, 2, 2), + /* 10 */ V(1, 3, 1), + /* 11 */ V(1, 3, 1), + + /* 0011 ... */ + /* 00 */ V(3, 1, 1), /* 44 */ + /* 01 */ V(3, 1, 1), + /* 10 */ V(0, 3, 2), + /* 11 */ V(3, 0, 2), + + /* 0100 ... */ + /* 0 */ V(2, 2, 1), /* 48 */ + /* 1 */ V(0, 2, 1), + + /* 0000 0000 ... */ + /* 0 */ V(5, 5, 1), /* 50 */ + /* 1 */ V(4, 5, 1), + + /* 0000 0011 ... */ + /* 0 */ V(5, 4, 1), /* 52 */ + /* 1 */ V(0, 5, 1) +}; + +static +union huffpair const hufftab10[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 2), + /* 0011 */ V(1, 1, 4), + /* 0100 */ V(0, 1, 3), + /* 0101 */ V(0, 1, 3), + /* 0110 */ V(1, 0, 3), + /* 0111 */ V(1, 0, 3), + /* 1000 */ V(0, 0, 1), + /* 1001 */ V(0, 0, 1), + /* 1010 */ V(0, 0, 1), + /* 1011 */ V(0, 0, 1), + /* 1100 */ V(0, 0, 1), + /* 1101 */ V(0, 0, 1), + /* 1110 */ V(0, 0, 1), + /* 1111 */ V(0, 0, 1), + + /* 0000 ... */ + /* 0000 */ PTR(52, 3), /* 16 */ + /* 0001 */ PTR(60, 2), + /* 0010 */ PTR(64, 3), + /* 0011 */ PTR(72, 1), + /* 0100 */ PTR(74, 2), + /* 0101 */ PTR(78, 2), + /* 0110 */ PTR(82, 2), + /* 0111 */ V(1, 7, 4), + /* 1000 */ V(7, 1, 4), + /* 1001 */ PTR(86, 1), + /* 1010 */ PTR(88, 2), + /* 1011 */ PTR(92, 2), + /* 1100 */ V(1, 6, 4), + /* 1101 */ V(6, 1, 4), + /* 1110 */ V(6, 0, 4), + /* 1111 */ PTR(96, 1), + + /* 0001 ... */ + /* 0000 */ PTR(98, 1), /* 32 */ + /* 0001 */ PTR(100, 1), + /* 0010 */ V(1, 4, 4), + /* 0011 */ V(4, 1, 4), + /* 0100 */ V(4, 0, 4), + /* 0101 */ V(2, 3, 4), + /* 0110 */ V(3, 2, 4), + /* 0111 */ V(0, 3, 4), + /* 1000 */ V(1, 3, 3), + /* 1001 */ V(1, 3, 3), + /* 1010 */ V(3, 1, 3), + /* 1011 */ V(3, 1, 3), + /* 1100 */ V(3, 0, 3), + /* 1101 */ V(3, 0, 3), + /* 1110 */ V(2, 2, 3), + /* 1111 */ V(2, 2, 3), + + /* 0010 ... */ + /* 00 */ V(1, 2, 2), /* 48 */ + /* 01 */ V(2, 1, 2), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 000 */ V(7, 7, 3), /* 52 */ + /* 001 */ V(6, 7, 3), + /* 010 */ V(7, 6, 3), + /* 011 */ V(5, 7, 3), + /* 100 */ V(7, 5, 3), + /* 101 */ V(6, 6, 3), + /* 110 */ V(4, 7, 2), + /* 111 */ V(4, 7, 2), + + /* 0000 0001 ... */ + /* 00 */ V(7, 4, 2), /* 60 */ + /* 01 */ V(5, 6, 2), + /* 10 */ V(6, 5, 2), + /* 11 */ V(3, 7, 2), + + /* 0000 0010 ... */ + /* 000 */ V(7, 3, 2), /* 64 */ + /* 001 */ V(7, 3, 2), + /* 010 */ V(4, 6, 2), + /* 011 */ V(4, 6, 2), + /* 100 */ V(5, 5, 3), + /* 101 */ V(5, 4, 3), + /* 110 */ V(6, 3, 2), + /* 111 */ V(6, 3, 2), + + /* 0000 0011 ... */ + /* 0 */ V(2, 7, 1), /* 72 */ + /* 1 */ V(7, 2, 1), + + /* 0000 0100 ... */ + /* 00 */ V(6, 4, 2), /* 74 */ + /* 01 */ V(0, 7, 2), + /* 10 */ V(7, 0, 1), + /* 11 */ V(7, 0, 1), + + /* 0000 0101 ... */ + /* 00 */ V(6, 2, 1), /* 78 */ + /* 01 */ V(6, 2, 1), + /* 10 */ V(4, 5, 2), + /* 11 */ V(3, 5, 2), + + /* 0000 0110 ... */ + /* 00 */ V(0, 6, 1), /* 82 */ + /* 01 */ V(0, 6, 1), + /* 10 */ V(5, 3, 2), + /* 11 */ V(4, 4, 2), + + /* 0000 1001 ... */ + /* 0 */ V(3, 6, 1), /* 86 */ + /* 1 */ V(2, 6, 1), + + /* 0000 1010 ... */ + /* 00 */ V(2, 5, 2), /* 88 */ + /* 01 */ V(5, 2, 2), + /* 10 */ V(1, 5, 1), + /* 11 */ V(1, 5, 1), + + /* 0000 1011 ... */ + /* 00 */ V(5, 1, 1), /* 92 */ + /* 01 */ V(5, 1, 1), + /* 10 */ V(3, 4, 2), + /* 11 */ V(4, 3, 2), + + /* 0000 1111 ... */ + /* 0 */ V(0, 5, 1), /* 96 */ + /* 1 */ V(5, 0, 1), + + /* 0001 0000 ... */ + /* 0 */ V(2, 4, 1), /* 98 */ + /* 1 */ V(4, 2, 1), + + /* 0001 0001 ... */ + /* 0 */ V(3, 3, 1), /* 100 */ + /* 1 */ V(0, 4, 1) +}; + +static +union huffpair const hufftab11[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ PTR(64, 3), + /* 0100 */ V(1, 2, 4), + /* 0101 */ PTR(72, 1), + /* 0110 */ V(1, 1, 3), + /* 0111 */ V(1, 1, 3), + /* 1000 */ V(0, 1, 3), + /* 1001 */ V(0, 1, 3), + /* 1010 */ V(1, 0, 3), + /* 1011 */ V(1, 0, 3), + /* 1100 */ V(0, 0, 2), + /* 1101 */ V(0, 0, 2), + /* 1110 */ V(0, 0, 2), + /* 1111 */ V(0, 0, 2), + + /* 0000 ... */ + /* 0000 */ PTR(74, 2), /* 16 */ + /* 0001 */ PTR(78, 3), + /* 0010 */ PTR(86, 2), + /* 0011 */ PTR(90, 1), + /* 0100 */ PTR(92, 2), + /* 0101 */ V(2, 7, 4), + /* 0110 */ V(7, 2, 4), + /* 0111 */ PTR(96, 1), + /* 1000 */ V(7, 1, 3), + /* 1001 */ V(7, 1, 3), + /* 1010 */ V(1, 7, 4), + /* 1011 */ V(7, 0, 4), + /* 1100 */ V(3, 6, 4), + /* 1101 */ V(6, 3, 4), + /* 1110 */ V(6, 0, 4), + /* 1111 */ PTR(98, 1), + + /* 0001 ... */ + /* 0000 */ PTR(100, 1), /* 32 */ + /* 0001 */ V(1, 5, 4), + /* 0010 */ V(6, 2, 3), + /* 0011 */ V(6, 2, 3), + /* 0100 */ V(2, 6, 4), + /* 0101 */ V(0, 6, 4), + /* 0110 */ V(1, 6, 3), + /* 0111 */ V(1, 6, 3), + /* 1000 */ V(6, 1, 3), + /* 1001 */ V(6, 1, 3), + /* 1010 */ V(5, 1, 4), + /* 1011 */ V(3, 4, 4), + /* 1100 */ V(5, 0, 4), + /* 1101 */ PTR(102, 1), + /* 1110 */ V(2, 4, 4), + /* 1111 */ V(4, 2, 4), + + /* 0010 ... */ + /* 0000 */ V(1, 4, 4), /* 48 */ + /* 0001 */ V(4, 1, 4), + /* 0010 */ V(0, 4, 4), + /* 0011 */ V(4, 0, 4), + /* 0100 */ V(2, 3, 3), + /* 0101 */ V(2, 3, 3), + /* 0110 */ V(3, 2, 3), + /* 0111 */ V(3, 2, 3), + /* 1000 */ V(1, 3, 2), + /* 1001 */ V(1, 3, 2), + /* 1010 */ V(1, 3, 2), + /* 1011 */ V(1, 3, 2), + /* 1100 */ V(3, 1, 2), + /* 1101 */ V(3, 1, 2), + /* 1110 */ V(3, 1, 2), + /* 1111 */ V(3, 1, 2), + + /* 0011 ... */ + /* 000 */ V(0, 3, 3), /* 64 */ + /* 001 */ V(3, 0, 3), + /* 010 */ V(2, 2, 2), + /* 011 */ V(2, 2, 2), + /* 100 */ V(2, 1, 1), + /* 101 */ V(2, 1, 1), + /* 110 */ V(2, 1, 1), + /* 111 */ V(2, 1, 1), + + /* 0101 ... */ + /* 0 */ V(0, 2, 1), /* 72 */ + /* 1 */ V(2, 0, 1), + + /* 0000 0000 ... */ + /* 00 */ V(7, 7, 2), /* 74 */ + /* 01 */ V(6, 7, 2), + /* 10 */ V(7, 6, 2), + /* 11 */ V(7, 5, 2), + + /* 0000 0001 ... */ + /* 000 */ V(6, 6, 2), /* 78 */ + /* 001 */ V(6, 6, 2), + /* 010 */ V(4, 7, 2), + /* 011 */ V(4, 7, 2), + /* 100 */ V(7, 4, 2), + /* 101 */ V(7, 4, 2), + /* 110 */ V(5, 7, 3), + /* 111 */ V(5, 5, 3), + + /* 0000 0010 ... */ + /* 00 */ V(5, 6, 2), /* 86 */ + /* 01 */ V(6, 5, 2), + /* 10 */ V(3, 7, 1), + /* 11 */ V(3, 7, 1), + + /* 0000 0011 ... */ + /* 0 */ V(7, 3, 1), /* 90 */ + /* 1 */ V(4, 6, 1), + + /* 0000 0100 ... */ + /* 00 */ V(4, 5, 2), /* 92 */ + /* 01 */ V(5, 4, 2), + /* 10 */ V(3, 5, 2), + /* 11 */ V(5, 3, 2), + + /* 0000 0111 ... */ + /* 0 */ V(6, 4, 1), /* 96 */ + /* 1 */ V(0, 7, 1), + + /* 0000 1111 ... */ + /* 0 */ V(4, 4, 1), /* 98 */ + /* 1 */ V(2, 5, 1), + + /* 0001 0000 ... */ + /* 0 */ V(5, 2, 1), /* 100 */ + /* 1 */ V(0, 5, 1), + + /* 0001 1101 ... */ + /* 0 */ V(4, 3, 1), /* 102 */ + /* 1 */ V(3, 3, 1) +}; + +static +union huffpair const hufftab12[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ PTR(64, 2), + /* 0100 */ PTR(68, 3), + /* 0101 */ PTR(76, 1), + /* 0110 */ V(1, 2, 4), + /* 0111 */ V(2, 1, 4), + /* 1000 */ PTR(78, 1), + /* 1001 */ V(0, 0, 4), + /* 1010 */ V(1, 1, 3), + /* 1011 */ V(1, 1, 3), + /* 1100 */ V(0, 1, 3), + /* 1101 */ V(0, 1, 3), + /* 1110 */ V(1, 0, 3), + /* 1111 */ V(1, 0, 3), + + /* 0000 ... */ + /* 0000 */ PTR(80, 2), /* 16 */ + /* 0001 */ PTR(84, 1), + /* 0010 */ PTR(86, 1), + /* 0011 */ PTR(88, 1), + /* 0100 */ V(5, 6, 4), + /* 0101 */ V(3, 7, 4), + /* 0110 */ PTR(90, 1), + /* 0111 */ V(2, 7, 4), + /* 1000 */ V(7, 2, 4), + /* 1001 */ V(4, 6, 4), + /* 1010 */ V(6, 4, 4), + /* 1011 */ V(1, 7, 4), + /* 1100 */ V(7, 1, 4), + /* 1101 */ PTR(92, 1), + /* 1110 */ V(3, 6, 4), + /* 1111 */ V(6, 3, 4), + + /* 0001 ... */ + /* 0000 */ V(4, 5, 4), /* 32 */ + /* 0001 */ V(5, 4, 4), + /* 0010 */ V(4, 4, 4), + /* 0011 */ PTR(94, 1), + /* 0100 */ V(2, 6, 3), + /* 0101 */ V(2, 6, 3), + /* 0110 */ V(6, 2, 3), + /* 0111 */ V(6, 2, 3), + /* 1000 */ V(6, 1, 3), + /* 1001 */ V(6, 1, 3), + /* 1010 */ V(1, 6, 4), + /* 1011 */ V(6, 0, 4), + /* 1100 */ V(3, 5, 4), + /* 1101 */ V(5, 3, 4), + /* 1110 */ V(2, 5, 4), + /* 1111 */ V(5, 2, 4), + + /* 0010 ... */ + /* 0000 */ V(1, 5, 3), /* 48 */ + /* 0001 */ V(1, 5, 3), + /* 0010 */ V(5, 1, 3), + /* 0011 */ V(5, 1, 3), + /* 0100 */ V(3, 4, 3), + /* 0101 */ V(3, 4, 3), + /* 0110 */ V(4, 3, 3), + /* 0111 */ V(4, 3, 3), + /* 1000 */ V(5, 0, 4), + /* 1001 */ V(0, 4, 4), + /* 1010 */ V(2, 4, 3), + /* 1011 */ V(2, 4, 3), + /* 1100 */ V(4, 2, 3), + /* 1101 */ V(4, 2, 3), + /* 1110 */ V(1, 4, 3), + /* 1111 */ V(1, 4, 3), + + /* 0011 ... */ + /* 00 */ V(3, 3, 2), /* 64 */ + /* 01 */ V(4, 1, 2), + /* 10 */ V(2, 3, 2), + /* 11 */ V(3, 2, 2), + + /* 0100 ... */ + /* 000 */ V(4, 0, 3), /* 68 */ + /* 001 */ V(0, 3, 3), + /* 010 */ V(3, 0, 2), + /* 011 */ V(3, 0, 2), + /* 100 */ V(1, 3, 1), + /* 101 */ V(1, 3, 1), + /* 110 */ V(1, 3, 1), + /* 111 */ V(1, 3, 1), + + /* 0101 ... */ + /* 0 */ V(3, 1, 1), /* 76 */ + /* 1 */ V(2, 2, 1), + + /* 1000 ... */ + /* 0 */ V(0, 2, 1), /* 78 */ + /* 1 */ V(2, 0, 1), + + /* 0000 0000 ... */ + /* 00 */ V(7, 7, 2), /* 80 */ + /* 01 */ V(6, 7, 2), + /* 10 */ V(7, 6, 1), + /* 11 */ V(7, 6, 1), + + /* 0000 0001 ... */ + /* 0 */ V(5, 7, 1), /* 84 */ + /* 1 */ V(7, 5, 1), + + /* 0000 0010 ... */ + /* 0 */ V(6, 6, 1), /* 86 */ + /* 1 */ V(4, 7, 1), + + /* 0000 0011 ... */ + /* 0 */ V(7, 4, 1), /* 88 */ + /* 1 */ V(6, 5, 1), + + /* 0000 0110 ... */ + /* 0 */ V(7, 3, 1), /* 90 */ + /* 1 */ V(5, 5, 1), + + /* 0000 1101 ... */ + /* 0 */ V(0, 7, 1), /* 92 */ + /* 1 */ V(7, 0, 1), + + /* 0001 0011 ... */ + /* 0 */ V(0, 6, 1), /* 94 */ + /* 1 */ V(0, 5, 1) +}; + +static +union huffpair const hufftab13[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ PTR(64, 2), + /* 0100 */ V(1, 1, 4), + /* 0101 */ V(0, 1, 4), + /* 0110 */ V(1, 0, 3), + /* 0111 */ V(1, 0, 3), + /* 1000 */ V(0, 0, 1), + /* 1001 */ V(0, 0, 1), + /* 1010 */ V(0, 0, 1), + /* 1011 */ V(0, 0, 1), + /* 1100 */ V(0, 0, 1), + /* 1101 */ V(0, 0, 1), + /* 1110 */ V(0, 0, 1), + /* 1111 */ V(0, 0, 1), + + /* 0000 ... */ + /* 0000 */ PTR(68, 4), /* 16 */ + /* 0001 */ PTR(84, 4), + /* 0010 */ PTR(100, 4), + /* 0011 */ PTR(116, 4), + /* 0100 */ PTR(132, 4), + /* 0101 */ PTR(148, 4), + /* 0110 */ PTR(164, 3), + /* 0111 */ PTR(172, 3), + /* 1000 */ PTR(180, 3), + /* 1001 */ PTR(188, 3), + /* 1010 */ PTR(196, 3), + /* 1011 */ PTR(204, 3), + /* 1100 */ PTR(212, 1), + /* 1101 */ PTR(214, 2), + /* 1110 */ PTR(218, 3), + /* 1111 */ PTR(226, 1), + + /* 0001 ... */ + /* 0000 */ PTR(228, 2), /* 32 */ + /* 0001 */ PTR(232, 2), + /* 0010 */ PTR(236, 2), + /* 0011 */ PTR(240, 2), + /* 0100 */ V(8, 1, 4), + /* 0101 */ PTR(244, 1), + /* 0110 */ PTR(246, 1), + /* 0111 */ PTR(248, 1), + /* 1000 */ PTR(250, 2), + /* 1001 */ PTR(254, 1), + /* 1010 */ V(1, 5, 4), + /* 1011 */ V(5, 1, 4), + /* 1100 */ PTR(256, 1), + /* 1101 */ PTR(258, 1), + /* 1110 */ PTR(260, 1), + /* 1111 */ V(1, 4, 4), + + /* 0010 ... */ + /* 0000 */ V(4, 1, 3), /* 48 */ + /* 0001 */ V(4, 1, 3), + /* 0010 */ V(0, 4, 4), + /* 0011 */ V(4, 0, 4), + /* 0100 */ V(2, 3, 4), + /* 0101 */ V(3, 2, 4), + /* 0110 */ V(1, 3, 3), + /* 0111 */ V(1, 3, 3), + /* 1000 */ V(3, 1, 3), + /* 1001 */ V(3, 1, 3), + /* 1010 */ V(0, 3, 3), + /* 1011 */ V(0, 3, 3), + /* 1100 */ V(3, 0, 3), + /* 1101 */ V(3, 0, 3), + /* 1110 */ V(2, 2, 3), + /* 1111 */ V(2, 2, 3), + + /* 0011 ... */ + /* 00 */ V(1, 2, 2), /* 64 */ + /* 01 */ V(2, 1, 2), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 0000 */ PTR(262, 4), /* 68 */ + /* 0001 */ PTR(278, 4), + /* 0010 */ PTR(294, 4), + /* 0011 */ PTR(310, 3), + /* 0100 */ PTR(318, 2), + /* 0101 */ PTR(322, 2), + /* 0110 */ PTR(326, 3), + /* 0111 */ PTR(334, 2), + /* 1000 */ PTR(338, 1), + /* 1001 */ PTR(340, 2), + /* 1010 */ PTR(344, 2), + /* 1011 */ PTR(348, 2), + /* 1100 */ PTR(352, 2), + /* 1101 */ PTR(356, 2), + /* 1110 */ V(1, 15, 4), + /* 1111 */ V(15, 1, 4), + + /* 0000 0001 ... */ + /* 0000 */ V(15, 0, 4), /* 84 */ + /* 0001 */ PTR(360, 1), + /* 0010 */ PTR(362, 1), + /* 0011 */ PTR(364, 1), + /* 0100 */ V(14, 2, 4), + /* 0101 */ PTR(366, 1), + /* 0110 */ V(1, 14, 4), + /* 0111 */ V(14, 1, 4), + /* 1000 */ PTR(368, 1), + /* 1001 */ PTR(370, 1), + /* 1010 */ PTR(372, 1), + /* 1011 */ PTR(374, 1), + /* 1100 */ PTR(376, 1), + /* 1101 */ PTR(378, 1), + /* 1110 */ V(12, 6, 4), + /* 1111 */ V(3, 13, 4), + + /* 0000 0010 ... */ + /* 0000 */ PTR(380, 1), /* 100 */ + /* 0001 */ V(2, 13, 4), + /* 0010 */ V(13, 2, 4), + /* 0011 */ V(1, 13, 4), + /* 0100 */ V(11, 7, 4), + /* 0101 */ PTR(382, 1), + /* 0110 */ PTR(384, 1), + /* 0111 */ V(12, 3, 4), + /* 1000 */ PTR(386, 1), + /* 1001 */ V(4, 11, 4), + /* 1010 */ V(13, 1, 3), + /* 1011 */ V(13, 1, 3), + /* 1100 */ V(0, 13, 4), + /* 1101 */ V(13, 0, 4), + /* 1110 */ V(8, 10, 4), + /* 1111 */ V(10, 8, 4), + + /* 0000 0011 ... */ + /* 0000 */ V(4, 12, 4), /* 116 */ + /* 0001 */ V(12, 4, 4), + /* 0010 */ V(6, 11, 4), + /* 0011 */ V(11, 6, 4), + /* 0100 */ V(3, 12, 3), + /* 0101 */ V(3, 12, 3), + /* 0110 */ V(2, 12, 3), + /* 0111 */ V(2, 12, 3), + /* 1000 */ V(12, 2, 3), + /* 1001 */ V(12, 2, 3), + /* 1010 */ V(5, 11, 3), + /* 1011 */ V(5, 11, 3), + /* 1100 */ V(11, 5, 4), + /* 1101 */ V(8, 9, 4), + /* 1110 */ V(1, 12, 3), + /* 1111 */ V(1, 12, 3), + + /* 0000 0100 ... */ + /* 0000 */ V(12, 1, 3), /* 132 */ + /* 0001 */ V(12, 1, 3), + /* 0010 */ V(9, 8, 4), + /* 0011 */ V(0, 12, 4), + /* 0100 */ V(12, 0, 3), + /* 0101 */ V(12, 0, 3), + /* 0110 */ V(11, 4, 4), + /* 0111 */ V(6, 10, 4), + /* 1000 */ V(10, 6, 4), + /* 1001 */ V(7, 9, 4), + /* 1010 */ V(3, 11, 3), + /* 1011 */ V(3, 11, 3), + /* 1100 */ V(11, 3, 3), + /* 1101 */ V(11, 3, 3), + /* 1110 */ V(8, 8, 4), + /* 1111 */ V(5, 10, 4), + + /* 0000 0101 ... */ + /* 0000 */ V(2, 11, 3), /* 148 */ + /* 0001 */ V(2, 11, 3), + /* 0010 */ V(10, 5, 4), + /* 0011 */ V(6, 9, 4), + /* 0100 */ V(10, 4, 3), + /* 0101 */ V(10, 4, 3), + /* 0110 */ V(7, 8, 4), + /* 0111 */ V(8, 7, 4), + /* 1000 */ V(9, 4, 3), + /* 1001 */ V(9, 4, 3), + /* 1010 */ V(7, 7, 4), + /* 1011 */ V(7, 6, 4), + /* 1100 */ V(11, 2, 2), + /* 1101 */ V(11, 2, 2), + /* 1110 */ V(11, 2, 2), + /* 1111 */ V(11, 2, 2), + + /* 0000 0110 ... */ + /* 000 */ V(1, 11, 2), /* 164 */ + /* 001 */ V(1, 11, 2), + /* 010 */ V(11, 1, 2), + /* 011 */ V(11, 1, 2), + /* 100 */ V(0, 11, 3), + /* 101 */ V(11, 0, 3), + /* 110 */ V(9, 6, 3), + /* 111 */ V(4, 10, 3), + + /* 0000 0111 ... */ + /* 000 */ V(3, 10, 3), /* 172 */ + /* 001 */ V(10, 3, 3), + /* 010 */ V(5, 9, 3), + /* 011 */ V(9, 5, 3), + /* 100 */ V(2, 10, 2), + /* 101 */ V(2, 10, 2), + /* 110 */ V(10, 2, 2), + /* 111 */ V(10, 2, 2), + + /* 0000 1000 ... */ + /* 000 */ V(1, 10, 2), /* 180 */ + /* 001 */ V(1, 10, 2), + /* 010 */ V(10, 1, 2), + /* 011 */ V(10, 1, 2), + /* 100 */ V(0, 10, 3), + /* 101 */ V(6, 8, 3), + /* 110 */ V(10, 0, 2), + /* 111 */ V(10, 0, 2), + + /* 0000 1001 ... */ + /* 000 */ V(8, 6, 3), /* 188 */ + /* 001 */ V(4, 9, 3), + /* 010 */ V(9, 3, 2), + /* 011 */ V(9, 3, 2), + /* 100 */ V(3, 9, 3), + /* 101 */ V(5, 8, 3), + /* 110 */ V(8, 5, 3), + /* 111 */ V(6, 7, 3), + + /* 0000 1010 ... */ + /* 000 */ V(2, 9, 2), /* 196 */ + /* 001 */ V(2, 9, 2), + /* 010 */ V(9, 2, 2), + /* 011 */ V(9, 2, 2), + /* 100 */ V(5, 7, 3), + /* 101 */ V(7, 5, 3), + /* 110 */ V(3, 8, 2), + /* 111 */ V(3, 8, 2), + + /* 0000 1011 ... */ + /* 000 */ V(8, 3, 2), /* 204 */ + /* 001 */ V(8, 3, 2), + /* 010 */ V(6, 6, 3), + /* 011 */ V(4, 7, 3), + /* 100 */ V(7, 4, 3), + /* 101 */ V(5, 6, 3), + /* 110 */ V(6, 5, 3), + /* 111 */ V(7, 3, 3), + + /* 0000 1100 ... */ + /* 0 */ V(1, 9, 1), /* 212 */ + /* 1 */ V(9, 1, 1), + + /* 0000 1101 ... */ + /* 00 */ V(0, 9, 2), /* 214 */ + /* 01 */ V(9, 0, 2), + /* 10 */ V(4, 8, 2), + /* 11 */ V(8, 4, 2), + + /* 0000 1110 ... */ + /* 000 */ V(7, 2, 2), /* 218 */ + /* 001 */ V(7, 2, 2), + /* 010 */ V(4, 6, 3), + /* 011 */ V(6, 4, 3), + /* 100 */ V(2, 8, 1), + /* 101 */ V(2, 8, 1), + /* 110 */ V(2, 8, 1), + /* 111 */ V(2, 8, 1), + + /* 0000 1111 ... */ + /* 0 */ V(8, 2, 1), /* 226 */ + /* 1 */ V(1, 8, 1), + + /* 0001 0000 ... */ + /* 00 */ V(3, 7, 2), /* 228 */ + /* 01 */ V(2, 7, 2), + /* 10 */ V(1, 7, 1), + /* 11 */ V(1, 7, 1), + + /* 0001 0001 ... */ + /* 00 */ V(7, 1, 1), /* 232 */ + /* 01 */ V(7, 1, 1), + /* 10 */ V(5, 5, 2), + /* 11 */ V(0, 7, 2), + + /* 0001 0010 ... */ + /* 00 */ V(7, 0, 2), /* 236 */ + /* 01 */ V(3, 6, 2), + /* 10 */ V(6, 3, 2), + /* 11 */ V(4, 5, 2), + + /* 0001 0011 ... */ + /* 00 */ V(5, 4, 2), /* 240 */ + /* 01 */ V(2, 6, 2), + /* 10 */ V(6, 2, 2), + /* 11 */ V(3, 5, 2), + + /* 0001 0101 ... */ + /* 0 */ V(0, 8, 1), /* 244 */ + /* 1 */ V(8, 0, 1), + + /* 0001 0110 ... */ + /* 0 */ V(1, 6, 1), /* 246 */ + /* 1 */ V(6, 1, 1), + + /* 0001 0111 ... */ + /* 0 */ V(0, 6, 1), /* 248 */ + /* 1 */ V(6, 0, 1), + + /* 0001 1000 ... */ + /* 00 */ V(5, 3, 2), /* 250 */ + /* 01 */ V(4, 4, 2), + /* 10 */ V(2, 5, 1), + /* 11 */ V(2, 5, 1), + + /* 0001 1001 ... */ + /* 0 */ V(5, 2, 1), /* 254 */ + /* 1 */ V(0, 5, 1), + + /* 0001 1100 ... */ + /* 0 */ V(3, 4, 1), /* 256 */ + /* 1 */ V(4, 3, 1), + + /* 0001 1101 ... */ + /* 0 */ V(5, 0, 1), /* 258 */ + /* 1 */ V(2, 4, 1), + + /* 0001 1110 ... */ + /* 0 */ V(4, 2, 1), /* 260 */ + /* 1 */ V(3, 3, 1), + + /* 0000 0000 0000 ... */ + /* 0000 */ PTR(388, 3), /* 262 */ + /* 0001 */ V(15, 15, 4), + /* 0010 */ V(14, 15, 4), + /* 0011 */ V(13, 15, 4), + /* 0100 */ V(14, 14, 4), + /* 0101 */ V(12, 15, 4), + /* 0110 */ V(13, 14, 4), + /* 0111 */ V(11, 15, 4), + /* 1000 */ V(15, 11, 4), + /* 1001 */ V(12, 14, 4), + /* 1010 */ V(13, 12, 4), + /* 1011 */ PTR(396, 1), + /* 1100 */ V(14, 12, 3), + /* 1101 */ V(14, 12, 3), + /* 1110 */ V(13, 13, 3), + /* 1111 */ V(13, 13, 3), + + /* 0000 0000 0001 ... */ + /* 0000 */ V(15, 10, 4), /* 278 */ + /* 0001 */ V(12, 13, 4), + /* 0010 */ V(11, 14, 3), + /* 0011 */ V(11, 14, 3), + /* 0100 */ V(14, 11, 3), + /* 0101 */ V(14, 11, 3), + /* 0110 */ V(9, 15, 3), + /* 0111 */ V(9, 15, 3), + /* 1000 */ V(15, 9, 3), + /* 1001 */ V(15, 9, 3), + /* 1010 */ V(14, 10, 3), + /* 1011 */ V(14, 10, 3), + /* 1100 */ V(11, 13, 3), + /* 1101 */ V(11, 13, 3), + /* 1110 */ V(13, 11, 3), + /* 1111 */ V(13, 11, 3), + + /* 0000 0000 0010 ... */ + /* 0000 */ V(8, 15, 3), /* 294 */ + /* 0001 */ V(8, 15, 3), + /* 0010 */ V(15, 8, 3), + /* 0011 */ V(15, 8, 3), + /* 0100 */ V(12, 12, 3), + /* 0101 */ V(12, 12, 3), + /* 0110 */ V(10, 14, 4), + /* 0111 */ V(9, 14, 4), + /* 1000 */ V(8, 14, 3), + /* 1001 */ V(8, 14, 3), + /* 1010 */ V(7, 15, 4), + /* 1011 */ V(7, 14, 4), + /* 1100 */ V(15, 7, 2), + /* 1101 */ V(15, 7, 2), + /* 1110 */ V(15, 7, 2), + /* 1111 */ V(15, 7, 2), + + /* 0000 0000 0011 ... */ + /* 000 */ V(13, 10, 2), /* 310 */ + /* 001 */ V(13, 10, 2), + /* 010 */ V(10, 13, 3), + /* 011 */ V(11, 12, 3), + /* 100 */ V(12, 11, 3), + /* 101 */ V(15, 6, 3), + /* 110 */ V(6, 15, 2), + /* 111 */ V(6, 15, 2), + + /* 0000 0000 0100 ... */ + /* 00 */ V(14, 8, 2), /* 318 */ + /* 01 */ V(5, 15, 2), + /* 10 */ V(9, 13, 2), + /* 11 */ V(13, 9, 2), + + /* 0000 0000 0101 ... */ + /* 00 */ V(15, 5, 2), /* 322 */ + /* 01 */ V(14, 7, 2), + /* 10 */ V(10, 12, 2), + /* 11 */ V(11, 11, 2), + + /* 0000 0000 0110 ... */ + /* 000 */ V(4, 15, 2), /* 326 */ + /* 001 */ V(4, 15, 2), + /* 010 */ V(15, 4, 2), + /* 011 */ V(15, 4, 2), + /* 100 */ V(12, 10, 3), + /* 101 */ V(14, 6, 3), + /* 110 */ V(15, 3, 2), + /* 111 */ V(15, 3, 2), + + /* 0000 0000 0111 ... */ + /* 00 */ V(3, 15, 1), /* 334 */ + /* 01 */ V(3, 15, 1), + /* 10 */ V(8, 13, 2), + /* 11 */ V(13, 8, 2), + + /* 0000 0000 1000 ... */ + /* 0 */ V(2, 15, 1), /* 338 */ + /* 1 */ V(15, 2, 1), + + /* 0000 0000 1001 ... */ + /* 00 */ V(6, 14, 2), /* 340 */ + /* 01 */ V(9, 12, 2), + /* 10 */ V(0, 15, 1), + /* 11 */ V(0, 15, 1), + + /* 0000 0000 1010 ... */ + /* 00 */ V(12, 9, 2), /* 344 */ + /* 01 */ V(5, 14, 2), + /* 10 */ V(10, 11, 1), + /* 11 */ V(10, 11, 1), + + /* 0000 0000 1011 ... */ + /* 00 */ V(7, 13, 2), /* 348 */ + /* 01 */ V(13, 7, 2), + /* 10 */ V(4, 14, 1), + /* 11 */ V(4, 14, 1), + + /* 0000 0000 1100 ... */ + /* 00 */ V(12, 8, 2), /* 352 */ + /* 01 */ V(13, 6, 2), + /* 10 */ V(3, 14, 1), + /* 11 */ V(3, 14, 1), + + /* 0000 0000 1101 ... */ + /* 00 */ V(11, 9, 1), /* 356 */ + /* 01 */ V(11, 9, 1), + /* 10 */ V(9, 11, 2), + /* 11 */ V(10, 10, 2), + + /* 0000 0001 0001 ... */ + /* 0 */ V(11, 10, 1), /* 360 */ + /* 1 */ V(14, 5, 1), + + /* 0000 0001 0010 ... */ + /* 0 */ V(14, 4, 1), /* 362 */ + /* 1 */ V(8, 12, 1), + + /* 0000 0001 0011 ... */ + /* 0 */ V(6, 13, 1), /* 364 */ + /* 1 */ V(14, 3, 1), + + /* 0000 0001 0101 ... */ + /* 0 */ V(2, 14, 1), /* 366 */ + /* 1 */ V(0, 14, 1), + + /* 0000 0001 1000 ... */ + /* 0 */ V(14, 0, 1), /* 368 */ + /* 1 */ V(5, 13, 1), + + /* 0000 0001 1001 ... */ + /* 0 */ V(13, 5, 1), /* 370 */ + /* 1 */ V(7, 12, 1), + + /* 0000 0001 1010 ... */ + /* 0 */ V(12, 7, 1), /* 372 */ + /* 1 */ V(4, 13, 1), + + /* 0000 0001 1011 ... */ + /* 0 */ V(8, 11, 1), /* 374 */ + /* 1 */ V(11, 8, 1), + + /* 0000 0001 1100 ... */ + /* 0 */ V(13, 4, 1), /* 376 */ + /* 1 */ V(9, 10, 1), + + /* 0000 0001 1101 ... */ + /* 0 */ V(10, 9, 1), /* 378 */ + /* 1 */ V(6, 12, 1), + + /* 0000 0010 0000 ... */ + /* 0 */ V(13, 3, 1), /* 380 */ + /* 1 */ V(7, 11, 1), + + /* 0000 0010 0101 ... */ + /* 0 */ V(5, 12, 1), /* 382 */ + /* 1 */ V(12, 5, 1), + + /* 0000 0010 0110 ... */ + /* 0 */ V(9, 9, 1), /* 384 */ + /* 1 */ V(7, 10, 1), + + /* 0000 0010 1000 ... */ + /* 0 */ V(10, 7, 1), /* 386 */ + /* 1 */ V(9, 7, 1), + + /* 0000 0000 0000 0000 ... */ + /* 000 */ V(15, 14, 3), /* 388 */ + /* 001 */ V(15, 12, 3), + /* 010 */ V(15, 13, 2), + /* 011 */ V(15, 13, 2), + /* 100 */ V(14, 13, 1), + /* 101 */ V(14, 13, 1), + /* 110 */ V(14, 13, 1), + /* 111 */ V(14, 13, 1), + + /* 0000 0000 0000 1011 ... */ + /* 0 */ V(10, 15, 1), /* 396 */ + /* 1 */ V(14, 9, 1) +}; + +static +union huffpair const hufftab15[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ PTR(64, 4), + /* 0100 */ PTR(80, 4), + /* 0101 */ PTR(96, 3), + /* 0110 */ PTR(104, 3), + /* 0111 */ PTR(112, 2), + /* 1000 */ PTR(116, 1), + /* 1001 */ PTR(118, 1), + /* 1010 */ V(1, 1, 3), + /* 1011 */ V(1, 1, 3), + /* 1100 */ V(0, 1, 4), + /* 1101 */ V(1, 0, 4), + /* 1110 */ V(0, 0, 3), + /* 1111 */ V(0, 0, 3), + + /* 0000 ... */ + /* 0000 */ PTR(120, 4), /* 16 */ + /* 0001 */ PTR(136, 4), + /* 0010 */ PTR(152, 4), + /* 0011 */ PTR(168, 4), + /* 0100 */ PTR(184, 4), + /* 0101 */ PTR(200, 3), + /* 0110 */ PTR(208, 3), + /* 0111 */ PTR(216, 4), + /* 1000 */ PTR(232, 3), + /* 1001 */ PTR(240, 3), + /* 1010 */ PTR(248, 3), + /* 1011 */ PTR(256, 3), + /* 1100 */ PTR(264, 2), + /* 1101 */ PTR(268, 3), + /* 1110 */ PTR(276, 3), + /* 1111 */ PTR(284, 2), + + /* 0001 ... */ + /* 0000 */ PTR(288, 2), /* 32 */ + /* 0001 */ PTR(292, 2), + /* 0010 */ PTR(296, 2), + /* 0011 */ PTR(300, 2), + /* 0100 */ PTR(304, 2), + /* 0101 */ PTR(308, 2), + /* 0110 */ PTR(312, 2), + /* 0111 */ PTR(316, 2), + /* 1000 */ PTR(320, 1), + /* 1001 */ PTR(322, 1), + /* 1010 */ PTR(324, 1), + /* 1011 */ PTR(326, 2), + /* 1100 */ PTR(330, 1), + /* 1101 */ PTR(332, 1), + /* 1110 */ PTR(334, 2), + /* 1111 */ PTR(338, 1), + + /* 0010 ... */ + /* 0000 */ PTR(340, 1), /* 48 */ + /* 0001 */ PTR(342, 1), + /* 0010 */ V(9, 1, 4), + /* 0011 */ PTR(344, 1), + /* 0100 */ PTR(346, 1), + /* 0101 */ PTR(348, 1), + /* 0110 */ PTR(350, 1), + /* 0111 */ PTR(352, 1), + /* 1000 */ V(2, 8, 4), + /* 1001 */ V(8, 2, 4), + /* 1010 */ V(1, 8, 4), + /* 1011 */ V(8, 1, 4), + /* 1100 */ PTR(354, 1), + /* 1101 */ PTR(356, 1), + /* 1110 */ PTR(358, 1), + /* 1111 */ PTR(360, 1), + + /* 0011 ... */ + /* 0000 */ V(2, 7, 4), /* 64 */ + /* 0001 */ V(7, 2, 4), + /* 0010 */ V(6, 4, 4), + /* 0011 */ V(1, 7, 4), + /* 0100 */ V(5, 5, 4), + /* 0101 */ V(7, 1, 4), + /* 0110 */ PTR(362, 1), + /* 0111 */ V(3, 6, 4), + /* 1000 */ V(6, 3, 4), + /* 1001 */ V(4, 5, 4), + /* 1010 */ V(5, 4, 4), + /* 1011 */ V(2, 6, 4), + /* 1100 */ V(6, 2, 4), + /* 1101 */ V(1, 6, 4), + /* 1110 */ PTR(364, 1), + /* 1111 */ V(3, 5, 4), + + /* 0100 ... */ + /* 0000 */ V(6, 1, 3), /* 80 */ + /* 0001 */ V(6, 1, 3), + /* 0010 */ V(5, 3, 4), + /* 0011 */ V(4, 4, 4), + /* 0100 */ V(2, 5, 3), + /* 0101 */ V(2, 5, 3), + /* 0110 */ V(5, 2, 3), + /* 0111 */ V(5, 2, 3), + /* 1000 */ V(1, 5, 3), + /* 1001 */ V(1, 5, 3), + /* 1010 */ V(5, 1, 3), + /* 1011 */ V(5, 1, 3), + /* 1100 */ V(0, 5, 4), + /* 1101 */ V(5, 0, 4), + /* 1110 */ V(3, 4, 3), + /* 1111 */ V(3, 4, 3), + + /* 0101 ... */ + /* 000 */ V(4, 3, 3), /* 96 */ + /* 001 */ V(2, 4, 3), + /* 010 */ V(4, 2, 3), + /* 011 */ V(3, 3, 3), + /* 100 */ V(4, 1, 2), + /* 101 */ V(4, 1, 2), + /* 110 */ V(1, 4, 3), + /* 111 */ V(0, 4, 3), + + /* 0110 ... */ + /* 000 */ V(2, 3, 2), /* 104 */ + /* 001 */ V(2, 3, 2), + /* 010 */ V(3, 2, 2), + /* 011 */ V(3, 2, 2), + /* 100 */ V(4, 0, 3), + /* 101 */ V(0, 3, 3), + /* 110 */ V(1, 3, 2), + /* 111 */ V(1, 3, 2), + + /* 0111 ... */ + /* 00 */ V(3, 1, 2), /* 112 */ + /* 01 */ V(3, 0, 2), + /* 10 */ V(2, 2, 1), + /* 11 */ V(2, 2, 1), + + /* 1000 ... */ + /* 0 */ V(1, 2, 1), /* 116 */ + /* 1 */ V(2, 1, 1), + + /* 1001 ... */ + /* 0 */ V(0, 2, 1), /* 118 */ + /* 1 */ V(2, 0, 1), + + /* 0000 0000 ... */ + /* 0000 */ PTR(366, 1), /* 120 */ + /* 0001 */ PTR(368, 1), + /* 0010 */ V(14, 14, 4), + /* 0011 */ PTR(370, 1), + /* 0100 */ PTR(372, 1), + /* 0101 */ PTR(374, 1), + /* 0110 */ V(15, 11, 4), + /* 0111 */ PTR(376, 1), + /* 1000 */ V(13, 13, 4), + /* 1001 */ V(10, 15, 4), + /* 1010 */ V(15, 10, 4), + /* 1011 */ V(11, 14, 4), + /* 1100 */ V(14, 11, 4), + /* 1101 */ V(12, 13, 4), + /* 1110 */ V(13, 12, 4), + /* 1111 */ V(9, 15, 4), + + /* 0000 0001 ... */ + /* 0000 */ V(15, 9, 4), /* 136 */ + /* 0001 */ V(14, 10, 4), + /* 0010 */ V(11, 13, 4), + /* 0011 */ V(13, 11, 4), + /* 0100 */ V(8, 15, 4), + /* 0101 */ V(15, 8, 4), + /* 0110 */ V(12, 12, 4), + /* 0111 */ V(9, 14, 4), + /* 1000 */ V(14, 9, 4), + /* 1001 */ V(7, 15, 4), + /* 1010 */ V(15, 7, 4), + /* 1011 */ V(10, 13, 4), + /* 1100 */ V(13, 10, 4), + /* 1101 */ V(11, 12, 4), + /* 1110 */ V(6, 15, 4), + /* 1111 */ PTR(378, 1), + + /* 0000 0010 ... */ + /* 0000 */ V(12, 11, 3), /* 152 */ + /* 0001 */ V(12, 11, 3), + /* 0010 */ V(15, 6, 3), + /* 0011 */ V(15, 6, 3), + /* 0100 */ V(8, 14, 4), + /* 0101 */ V(14, 8, 4), + /* 0110 */ V(5, 15, 4), + /* 0111 */ V(9, 13, 4), + /* 1000 */ V(15, 5, 3), + /* 1001 */ V(15, 5, 3), + /* 1010 */ V(7, 14, 3), + /* 1011 */ V(7, 14, 3), + /* 1100 */ V(14, 7, 3), + /* 1101 */ V(14, 7, 3), + /* 1110 */ V(10, 12, 3), + /* 1111 */ V(10, 12, 3), + + /* 0000 0011 ... */ + /* 0000 */ V(12, 10, 3), /* 168 */ + /* 0001 */ V(12, 10, 3), + /* 0010 */ V(11, 11, 3), + /* 0011 */ V(11, 11, 3), + /* 0100 */ V(13, 9, 4), + /* 0101 */ V(8, 13, 4), + /* 0110 */ V(4, 15, 3), + /* 0111 */ V(4, 15, 3), + /* 1000 */ V(15, 4, 3), + /* 1001 */ V(15, 4, 3), + /* 1010 */ V(3, 15, 3), + /* 1011 */ V(3, 15, 3), + /* 1100 */ V(15, 3, 3), + /* 1101 */ V(15, 3, 3), + /* 1110 */ V(13, 8, 3), + /* 1111 */ V(13, 8, 3), + + /* 0000 0100 ... */ + /* 0000 */ V(14, 6, 3), /* 184 */ + /* 0001 */ V(14, 6, 3), + /* 0010 */ V(2, 15, 3), + /* 0011 */ V(2, 15, 3), + /* 0100 */ V(15, 2, 3), + /* 0101 */ V(15, 2, 3), + /* 0110 */ V(6, 14, 4), + /* 0111 */ V(15, 0, 4), + /* 1000 */ V(1, 15, 3), + /* 1001 */ V(1, 15, 3), + /* 1010 */ V(15, 1, 3), + /* 1011 */ V(15, 1, 3), + /* 1100 */ V(9, 12, 3), + /* 1101 */ V(9, 12, 3), + /* 1110 */ V(12, 9, 3), + /* 1111 */ V(12, 9, 3), + + /* 0000 0101 ... */ + /* 000 */ V(5, 14, 3), /* 200 */ + /* 001 */ V(10, 11, 3), + /* 010 */ V(11, 10, 3), + /* 011 */ V(14, 5, 3), + /* 100 */ V(7, 13, 3), + /* 101 */ V(13, 7, 3), + /* 110 */ V(4, 14, 3), + /* 111 */ V(14, 4, 3), + + /* 0000 0110 ... */ + /* 000 */ V(8, 12, 3), /* 208 */ + /* 001 */ V(12, 8, 3), + /* 010 */ V(3, 14, 3), + /* 011 */ V(6, 13, 3), + /* 100 */ V(13, 6, 3), + /* 101 */ V(14, 3, 3), + /* 110 */ V(9, 11, 3), + /* 111 */ V(11, 9, 3), + + /* 0000 0111 ... */ + /* 0000 */ V(2, 14, 3), /* 216 */ + /* 0001 */ V(2, 14, 3), + /* 0010 */ V(10, 10, 3), + /* 0011 */ V(10, 10, 3), + /* 0100 */ V(14, 2, 3), + /* 0101 */ V(14, 2, 3), + /* 0110 */ V(1, 14, 3), + /* 0111 */ V(1, 14, 3), + /* 1000 */ V(14, 1, 3), + /* 1001 */ V(14, 1, 3), + /* 1010 */ V(0, 14, 4), + /* 1011 */ V(14, 0, 4), + /* 1100 */ V(5, 13, 3), + /* 1101 */ V(5, 13, 3), + /* 1110 */ V(13, 5, 3), + /* 1111 */ V(13, 5, 3), + + /* 0000 1000 ... */ + /* 000 */ V(7, 12, 3), /* 232 */ + /* 001 */ V(12, 7, 3), + /* 010 */ V(4, 13, 3), + /* 011 */ V(8, 11, 3), + /* 100 */ V(13, 4, 2), + /* 101 */ V(13, 4, 2), + /* 110 */ V(11, 8, 3), + /* 111 */ V(9, 10, 3), + + /* 0000 1001 ... */ + /* 000 */ V(10, 9, 3), /* 240 */ + /* 001 */ V(6, 12, 3), + /* 010 */ V(12, 6, 3), + /* 011 */ V(3, 13, 3), + /* 100 */ V(13, 3, 2), + /* 101 */ V(13, 3, 2), + /* 110 */ V(13, 2, 2), + /* 111 */ V(13, 2, 2), + + /* 0000 1010 ... */ + /* 000 */ V(2, 13, 3), /* 248 */ + /* 001 */ V(0, 13, 3), + /* 010 */ V(1, 13, 2), + /* 011 */ V(1, 13, 2), + /* 100 */ V(7, 11, 2), + /* 101 */ V(7, 11, 2), + /* 110 */ V(11, 7, 2), + /* 111 */ V(11, 7, 2), + + /* 0000 1011 ... */ + /* 000 */ V(13, 1, 2), /* 256 */ + /* 001 */ V(13, 1, 2), + /* 010 */ V(5, 12, 3), + /* 011 */ V(13, 0, 3), + /* 100 */ V(12, 5, 2), + /* 101 */ V(12, 5, 2), + /* 110 */ V(8, 10, 2), + /* 111 */ V(8, 10, 2), + + /* 0000 1100 ... */ + /* 00 */ V(10, 8, 2), /* 264 */ + /* 01 */ V(4, 12, 2), + /* 10 */ V(12, 4, 2), + /* 11 */ V(6, 11, 2), + + /* 0000 1101 ... */ + /* 000 */ V(11, 6, 2), /* 268 */ + /* 001 */ V(11, 6, 2), + /* 010 */ V(9, 9, 3), + /* 011 */ V(0, 12, 3), + /* 100 */ V(3, 12, 2), + /* 101 */ V(3, 12, 2), + /* 110 */ V(12, 3, 2), + /* 111 */ V(12, 3, 2), + + /* 0000 1110 ... */ + /* 000 */ V(7, 10, 2), /* 276 */ + /* 001 */ V(7, 10, 2), + /* 010 */ V(10, 7, 2), + /* 011 */ V(10, 7, 2), + /* 100 */ V(10, 6, 2), + /* 101 */ V(10, 6, 2), + /* 110 */ V(12, 0, 3), + /* 111 */ V(0, 11, 3), + + /* 0000 1111 ... */ + /* 00 */ V(12, 2, 1), /* 284 */ + /* 01 */ V(12, 2, 1), + /* 10 */ V(2, 12, 2), + /* 11 */ V(5, 11, 2), + + /* 0001 0000 ... */ + /* 00 */ V(11, 5, 2), /* 288 */ + /* 01 */ V(1, 12, 2), + /* 10 */ V(8, 9, 2), + /* 11 */ V(9, 8, 2), + + /* 0001 0001 ... */ + /* 00 */ V(12, 1, 2), /* 292 */ + /* 01 */ V(4, 11, 2), + /* 10 */ V(11, 4, 2), + /* 11 */ V(6, 10, 2), + + /* 0001 0010 ... */ + /* 00 */ V(3, 11, 2), /* 296 */ + /* 01 */ V(7, 9, 2), + /* 10 */ V(11, 3, 1), + /* 11 */ V(11, 3, 1), + + /* 0001 0011 ... */ + /* 00 */ V(9, 7, 2), /* 300 */ + /* 01 */ V(8, 8, 2), + /* 10 */ V(2, 11, 2), + /* 11 */ V(5, 10, 2), + + /* 0001 0100 ... */ + /* 00 */ V(11, 2, 1), /* 304 */ + /* 01 */ V(11, 2, 1), + /* 10 */ V(10, 5, 2), + /* 11 */ V(1, 11, 2), + + /* 0001 0101 ... */ + /* 00 */ V(11, 1, 1), /* 308 */ + /* 01 */ V(11, 1, 1), + /* 10 */ V(11, 0, 2), + /* 11 */ V(6, 9, 2), + + /* 0001 0110 ... */ + /* 00 */ V(9, 6, 2), /* 312 */ + /* 01 */ V(4, 10, 2), + /* 10 */ V(10, 4, 2), + /* 11 */ V(7, 8, 2), + + /* 0001 0111 ... */ + /* 00 */ V(8, 7, 2), /* 316 */ + /* 01 */ V(3, 10, 2), + /* 10 */ V(10, 3, 1), + /* 11 */ V(10, 3, 1), + + /* 0001 1000 ... */ + /* 0 */ V(5, 9, 1), /* 320 */ + /* 1 */ V(9, 5, 1), + + /* 0001 1001 ... */ + /* 0 */ V(2, 10, 1), /* 322 */ + /* 1 */ V(10, 2, 1), + + /* 0001 1010 ... */ + /* 0 */ V(1, 10, 1), /* 324 */ + /* 1 */ V(10, 1, 1), + + /* 0001 1011 ... */ + /* 00 */ V(0, 10, 2), /* 326 */ + /* 01 */ V(10, 0, 2), + /* 10 */ V(6, 8, 1), + /* 11 */ V(6, 8, 1), + + /* 0001 1100 ... */ + /* 0 */ V(8, 6, 1), /* 330 */ + /* 1 */ V(4, 9, 1), + + /* 0001 1101 ... */ + /* 0 */ V(9, 4, 1), /* 332 */ + /* 1 */ V(3, 9, 1), + + /* 0001 1110 ... */ + /* 00 */ V(9, 3, 1), /* 334 */ + /* 01 */ V(9, 3, 1), + /* 10 */ V(7, 7, 2), + /* 11 */ V(0, 9, 2), + + /* 0001 1111 ... */ + /* 0 */ V(5, 8, 1), /* 338 */ + /* 1 */ V(8, 5, 1), + + /* 0010 0000 ... */ + /* 0 */ V(2, 9, 1), /* 340 */ + /* 1 */ V(6, 7, 1), + + /* 0010 0001 ... */ + /* 0 */ V(7, 6, 1), /* 342 */ + /* 1 */ V(9, 2, 1), + + /* 0010 0011 ... */ + /* 0 */ V(1, 9, 1), /* 344 */ + /* 1 */ V(9, 0, 1), + + /* 0010 0100 ... */ + /* 0 */ V(4, 8, 1), /* 346 */ + /* 1 */ V(8, 4, 1), + + /* 0010 0101 ... */ + /* 0 */ V(5, 7, 1), /* 348 */ + /* 1 */ V(7, 5, 1), + + /* 0010 0110 ... */ + /* 0 */ V(3, 8, 1), /* 350 */ + /* 1 */ V(8, 3, 1), + + /* 0010 0111 ... */ + /* 0 */ V(6, 6, 1), /* 352 */ + /* 1 */ V(4, 7, 1), + + /* 0010 1100 ... */ + /* 0 */ V(7, 4, 1), /* 354 */ + /* 1 */ V(0, 8, 1), + + /* 0010 1101 ... */ + /* 0 */ V(8, 0, 1), /* 356 */ + /* 1 */ V(5, 6, 1), + + /* 0010 1110 ... */ + /* 0 */ V(6, 5, 1), /* 358 */ + /* 1 */ V(3, 7, 1), + + /* 0010 1111 ... */ + /* 0 */ V(7, 3, 1), /* 360 */ + /* 1 */ V(4, 6, 1), + + /* 0011 0110 ... */ + /* 0 */ V(0, 7, 1), /* 362 */ + /* 1 */ V(7, 0, 1), + + /* 0011 1110 ... */ + /* 0 */ V(0, 6, 1), /* 364 */ + /* 1 */ V(6, 0, 1), + + /* 0000 0000 0000 ... */ + /* 0 */ V(15, 15, 1), /* 366 */ + /* 1 */ V(14, 15, 1), + + /* 0000 0000 0001 ... */ + /* 0 */ V(15, 14, 1), /* 368 */ + /* 1 */ V(13, 15, 1), + + /* 0000 0000 0011 ... */ + /* 0 */ V(15, 13, 1), /* 370 */ + /* 1 */ V(12, 15, 1), + + /* 0000 0000 0100 ... */ + /* 0 */ V(15, 12, 1), /* 372 */ + /* 1 */ V(13, 14, 1), + + /* 0000 0000 0101 ... */ + /* 0 */ V(14, 13, 1), /* 374 */ + /* 1 */ V(11, 15, 1), + + /* 0000 0000 0111 ... */ + /* 0 */ V(12, 14, 1), /* 376 */ + /* 1 */ V(14, 12, 1), + + /* 0000 0001 1111 ... */ + /* 0 */ V(10, 14, 1), /* 378 */ + /* 1 */ V(0, 15, 1) +}; + +static +union huffpair const hufftab16[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ PTR(64, 2), + /* 0100 */ V(1, 1, 4), + /* 0101 */ V(0, 1, 4), + /* 0110 */ V(1, 0, 3), + /* 0111 */ V(1, 0, 3), + /* 1000 */ V(0, 0, 1), + /* 1001 */ V(0, 0, 1), + /* 1010 */ V(0, 0, 1), + /* 1011 */ V(0, 0, 1), + /* 1100 */ V(0, 0, 1), + /* 1101 */ V(0, 0, 1), + /* 1110 */ V(0, 0, 1), + /* 1111 */ V(0, 0, 1), + + /* 0000 ... */ + /* 0000 */ PTR(68, 3), /* 16 */ + /* 0001 */ PTR(76, 3), + /* 0010 */ PTR(84, 2), + /* 0011 */ V(15, 15, 4), + /* 0100 */ PTR(88, 2), + /* 0101 */ PTR(92, 1), + /* 0110 */ PTR(94, 4), + /* 0111 */ V(15, 2, 4), + /* 1000 */ PTR(110, 1), + /* 1001 */ V(1, 15, 4), + /* 1010 */ V(15, 1, 4), + /* 1011 */ PTR(112, 4), + /* 1100 */ PTR(128, 4), + /* 1101 */ PTR(144, 4), + /* 1110 */ PTR(160, 4), + /* 1111 */ PTR(176, 4), + + /* 0001 ... */ + /* 0000 */ PTR(192, 4), /* 32 */ + /* 0001 */ PTR(208, 3), + /* 0010 */ PTR(216, 3), + /* 0011 */ PTR(224, 3), + /* 0100 */ PTR(232, 3), + /* 0101 */ PTR(240, 3), + /* 0110 */ PTR(248, 3), + /* 0111 */ PTR(256, 3), + /* 1000 */ PTR(264, 2), + /* 1001 */ PTR(268, 2), + /* 1010 */ PTR(272, 1), + /* 1011 */ PTR(274, 2), + /* 1100 */ PTR(278, 2), + /* 1101 */ PTR(282, 1), + /* 1110 */ V(5, 1, 4), + /* 1111 */ PTR(284, 1), + + /* 0010 ... */ + /* 0000 */ PTR(286, 1), /* 48 */ + /* 0001 */ PTR(288, 1), + /* 0010 */ PTR(290, 1), + /* 0011 */ V(1, 4, 4), + /* 0100 */ V(4, 1, 4), + /* 0101 */ PTR(292, 1), + /* 0110 */ V(2, 3, 4), + /* 0111 */ V(3, 2, 4), + /* 1000 */ V(1, 3, 3), + /* 1001 */ V(1, 3, 3), + /* 1010 */ V(3, 1, 3), + /* 1011 */ V(3, 1, 3), + /* 1100 */ V(0, 3, 4), + /* 1101 */ V(3, 0, 4), + /* 1110 */ V(2, 2, 3), + /* 1111 */ V(2, 2, 3), + + /* 0011 ... */ + /* 00 */ V(1, 2, 2), /* 64 */ + /* 01 */ V(2, 1, 2), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 000 */ V(14, 15, 3), /* 68 */ + /* 001 */ V(15, 14, 3), + /* 010 */ V(13, 15, 3), + /* 011 */ V(15, 13, 3), + /* 100 */ V(12, 15, 3), + /* 101 */ V(15, 12, 3), + /* 110 */ V(11, 15, 3), + /* 111 */ V(15, 11, 3), + + /* 0000 0001 ... */ + /* 000 */ V(10, 15, 2), /* 76 */ + /* 001 */ V(10, 15, 2), + /* 010 */ V(15, 10, 3), + /* 011 */ V(9, 15, 3), + /* 100 */ V(15, 9, 3), + /* 101 */ V(15, 8, 3), + /* 110 */ V(8, 15, 2), + /* 111 */ V(8, 15, 2), + + /* 0000 0010 ... */ + /* 00 */ V(7, 15, 2), /* 84 */ + /* 01 */ V(15, 7, 2), + /* 10 */ V(6, 15, 2), + /* 11 */ V(15, 6, 2), + + /* 0000 0100 ... */ + /* 00 */ V(5, 15, 2), /* 88 */ + /* 01 */ V(15, 5, 2), + /* 10 */ V(4, 15, 1), + /* 11 */ V(4, 15, 1), + + /* 0000 0101 ... */ + /* 0 */ V(15, 4, 1), /* 92 */ + /* 1 */ V(15, 3, 1), + + /* 0000 0110 ... */ + /* 0000 */ V(15, 0, 1), /* 94 */ + /* 0001 */ V(15, 0, 1), + /* 0010 */ V(15, 0, 1), + /* 0011 */ V(15, 0, 1), + /* 0100 */ V(15, 0, 1), + /* 0101 */ V(15, 0, 1), + /* 0110 */ V(15, 0, 1), + /* 0111 */ V(15, 0, 1), + /* 1000 */ V(3, 15, 2), + /* 1001 */ V(3, 15, 2), + /* 1010 */ V(3, 15, 2), + /* 1011 */ V(3, 15, 2), + /* 1100 */ PTR(294, 4), + /* 1101 */ PTR(310, 3), + /* 1110 */ PTR(318, 3), + /* 1111 */ PTR(326, 3), + + /* 0000 1000 ... */ + /* 0 */ V(2, 15, 1), /* 110 */ + /* 1 */ V(0, 15, 1), + + /* 0000 1011 ... */ + /* 0000 */ PTR(334, 2), /* 112 */ + /* 0001 */ PTR(338, 2), + /* 0010 */ PTR(342, 2), + /* 0011 */ PTR(346, 1), + /* 0100 */ PTR(348, 2), + /* 0101 */ PTR(352, 2), + /* 0110 */ PTR(356, 1), + /* 0111 */ PTR(358, 2), + /* 1000 */ PTR(362, 2), + /* 1001 */ PTR(366, 2), + /* 1010 */ PTR(370, 2), + /* 1011 */ V(14, 3, 4), + /* 1100 */ PTR(374, 1), + /* 1101 */ PTR(376, 1), + /* 1110 */ PTR(378, 1), + /* 1111 */ PTR(380, 1), + + /* 0000 1100 ... */ + /* 0000 */ PTR(382, 1), /* 128 */ + /* 0001 */ PTR(384, 1), + /* 0010 */ PTR(386, 1), + /* 0011 */ V(0, 13, 4), + /* 0100 */ PTR(388, 1), + /* 0101 */ PTR(390, 1), + /* 0110 */ PTR(392, 1), + /* 0111 */ V(3, 12, 4), + /* 1000 */ PTR(394, 1), + /* 1001 */ V(1, 12, 4), + /* 1010 */ V(12, 0, 4), + /* 1011 */ PTR(396, 1), + /* 1100 */ V(14, 2, 3), + /* 1101 */ V(14, 2, 3), + /* 1110 */ V(2, 14, 4), + /* 1111 */ V(1, 14, 4), + + /* 0000 1101 ... */ + /* 0000 */ V(13, 3, 4), /* 144 */ + /* 0001 */ V(2, 13, 4), + /* 0010 */ V(13, 2, 4), + /* 0011 */ V(13, 1, 4), + /* 0100 */ V(3, 11, 4), + /* 0101 */ PTR(398, 1), + /* 0110 */ V(1, 13, 3), + /* 0111 */ V(1, 13, 3), + /* 1000 */ V(12, 4, 4), + /* 1001 */ V(6, 11, 4), + /* 1010 */ V(12, 3, 4), + /* 1011 */ V(10, 7, 4), + /* 1100 */ V(2, 12, 3), + /* 1101 */ V(2, 12, 3), + /* 1110 */ V(12, 2, 4), + /* 1111 */ V(11, 5, 4), + + /* 0000 1110 ... */ + /* 0000 */ V(12, 1, 4), /* 160 */ + /* 0001 */ V(0, 12, 4), + /* 0010 */ V(4, 11, 4), + /* 0011 */ V(11, 4, 4), + /* 0100 */ V(6, 10, 4), + /* 0101 */ V(10, 6, 4), + /* 0110 */ V(11, 3, 3), + /* 0111 */ V(11, 3, 3), + /* 1000 */ V(5, 10, 4), + /* 1001 */ V(10, 5, 4), + /* 1010 */ V(2, 11, 3), + /* 1011 */ V(2, 11, 3), + /* 1100 */ V(11, 2, 3), + /* 1101 */ V(11, 2, 3), + /* 1110 */ V(1, 11, 3), + /* 1111 */ V(1, 11, 3), + + /* 0000 1111 ... */ + /* 0000 */ V(11, 1, 3), /* 176 */ + /* 0001 */ V(11, 1, 3), + /* 0010 */ V(0, 11, 4), + /* 0011 */ V(11, 0, 4), + /* 0100 */ V(6, 9, 4), + /* 0101 */ V(9, 6, 4), + /* 0110 */ V(4, 10, 4), + /* 0111 */ V(10, 4, 4), + /* 1000 */ V(7, 8, 4), + /* 1001 */ V(8, 7, 4), + /* 1010 */ V(10, 3, 3), + /* 1011 */ V(10, 3, 3), + /* 1100 */ V(3, 10, 4), + /* 1101 */ V(5, 9, 4), + /* 1110 */ V(2, 10, 3), + /* 1111 */ V(2, 10, 3), + + /* 0001 0000 ... */ + /* 0000 */ V(9, 5, 4), /* 192 */ + /* 0001 */ V(6, 8, 4), + /* 0010 */ V(10, 1, 3), + /* 0011 */ V(10, 1, 3), + /* 0100 */ V(8, 6, 4), + /* 0101 */ V(7, 7, 4), + /* 0110 */ V(9, 4, 3), + /* 0111 */ V(9, 4, 3), + /* 1000 */ V(4, 9, 4), + /* 1001 */ V(5, 7, 4), + /* 1010 */ V(6, 7, 3), + /* 1011 */ V(6, 7, 3), + /* 1100 */ V(10, 2, 2), + /* 1101 */ V(10, 2, 2), + /* 1110 */ V(10, 2, 2), + /* 1111 */ V(10, 2, 2), + + /* 0001 0001 ... */ + /* 000 */ V(1, 10, 2), /* 208 */ + /* 001 */ V(1, 10, 2), + /* 010 */ V(0, 10, 3), + /* 011 */ V(10, 0, 3), + /* 100 */ V(3, 9, 3), + /* 101 */ V(9, 3, 3), + /* 110 */ V(5, 8, 3), + /* 111 */ V(8, 5, 3), + + /* 0001 0010 ... */ + /* 000 */ V(2, 9, 2), /* 216 */ + /* 001 */ V(2, 9, 2), + /* 010 */ V(9, 2, 2), + /* 011 */ V(9, 2, 2), + /* 100 */ V(7, 6, 3), + /* 101 */ V(0, 9, 3), + /* 110 */ V(1, 9, 2), + /* 111 */ V(1, 9, 2), + + /* 0001 0011 ... */ + /* 000 */ V(9, 1, 2), /* 224 */ + /* 001 */ V(9, 1, 2), + /* 010 */ V(9, 0, 3), + /* 011 */ V(4, 8, 3), + /* 100 */ V(8, 4, 3), + /* 101 */ V(7, 5, 3), + /* 110 */ V(3, 8, 3), + /* 111 */ V(8, 3, 3), + + /* 0001 0100 ... */ + /* 000 */ V(6, 6, 3), /* 232 */ + /* 001 */ V(2, 8, 3), + /* 010 */ V(8, 2, 2), + /* 011 */ V(8, 2, 2), + /* 100 */ V(4, 7, 3), + /* 101 */ V(7, 4, 3), + /* 110 */ V(1, 8, 2), + /* 111 */ V(1, 8, 2), + + /* 0001 0101 ... */ + /* 000 */ V(8, 1, 2), /* 240 */ + /* 001 */ V(8, 1, 2), + /* 010 */ V(8, 0, 2), + /* 011 */ V(8, 0, 2), + /* 100 */ V(0, 8, 3), + /* 101 */ V(5, 6, 3), + /* 110 */ V(3, 7, 2), + /* 111 */ V(3, 7, 2), + + /* 0001 0110 ... */ + /* 000 */ V(7, 3, 2), /* 248 */ + /* 001 */ V(7, 3, 2), + /* 010 */ V(6, 5, 3), + /* 011 */ V(4, 6, 3), + /* 100 */ V(2, 7, 2), + /* 101 */ V(2, 7, 2), + /* 110 */ V(7, 2, 2), + /* 111 */ V(7, 2, 2), + + /* 0001 0111 ... */ + /* 000 */ V(6, 4, 3), /* 256 */ + /* 001 */ V(5, 5, 3), + /* 010 */ V(0, 7, 2), + /* 011 */ V(0, 7, 2), + /* 100 */ V(1, 7, 1), + /* 101 */ V(1, 7, 1), + /* 110 */ V(1, 7, 1), + /* 111 */ V(1, 7, 1), + + /* 0001 1000 ... */ + /* 00 */ V(7, 1, 1), /* 264 */ + /* 01 */ V(7, 1, 1), + /* 10 */ V(7, 0, 2), + /* 11 */ V(3, 6, 2), + + /* 0001 1001 ... */ + /* 00 */ V(6, 3, 2), /* 268 */ + /* 01 */ V(4, 5, 2), + /* 10 */ V(5, 4, 2), + /* 11 */ V(2, 6, 2), + + /* 0001 1010 ... */ + /* 0 */ V(6, 2, 1), /* 272 */ + /* 1 */ V(1, 6, 1), + + /* 0001 1011 ... */ + /* 00 */ V(6, 1, 1), /* 274 */ + /* 01 */ V(6, 1, 1), + /* 10 */ V(0, 6, 2), + /* 11 */ V(6, 0, 2), + + /* 0001 1100 ... */ + /* 00 */ V(5, 3, 1), /* 278 */ + /* 01 */ V(5, 3, 1), + /* 10 */ V(3, 5, 2), + /* 11 */ V(4, 4, 2), + + /* 0001 1101 ... */ + /* 0 */ V(2, 5, 1), /* 282 */ + /* 1 */ V(5, 2, 1), + + /* 0001 1111 ... */ + /* 0 */ V(1, 5, 1), /* 284 */ + /* 1 */ V(0, 5, 1), + + /* 0010 0000 ... */ + /* 0 */ V(3, 4, 1), /* 286 */ + /* 1 */ V(4, 3, 1), + + /* 0010 0001 ... */ + /* 0 */ V(5, 0, 1), /* 288 */ + /* 1 */ V(2, 4, 1), + + /* 0010 0010 ... */ + /* 0 */ V(4, 2, 1), /* 290 */ + /* 1 */ V(3, 3, 1), + + /* 0010 0101 ... */ + /* 0 */ V(0, 4, 1), /* 292 */ + /* 1 */ V(4, 0, 1), + + /* 0000 0110 1100 ... */ + /* 0000 */ V(12, 14, 4), /* 294 */ + /* 0001 */ PTR(400, 1), + /* 0010 */ V(13, 14, 3), + /* 0011 */ V(13, 14, 3), + /* 0100 */ V(14, 9, 3), + /* 0101 */ V(14, 9, 3), + /* 0110 */ V(14, 10, 4), + /* 0111 */ V(13, 9, 4), + /* 1000 */ V(14, 14, 2), + /* 1001 */ V(14, 14, 2), + /* 1010 */ V(14, 14, 2), + /* 1011 */ V(14, 14, 2), + /* 1100 */ V(14, 13, 3), + /* 1101 */ V(14, 13, 3), + /* 1110 */ V(14, 11, 3), + /* 1111 */ V(14, 11, 3), + + /* 0000 0110 1101 ... */ + /* 000 */ V(11, 14, 2), /* 310 */ + /* 001 */ V(11, 14, 2), + /* 010 */ V(12, 13, 2), + /* 011 */ V(12, 13, 2), + /* 100 */ V(13, 12, 3), + /* 101 */ V(13, 11, 3), + /* 110 */ V(10, 14, 2), + /* 111 */ V(10, 14, 2), + + /* 0000 0110 1110 ... */ + /* 000 */ V(12, 12, 2), /* 318 */ + /* 001 */ V(12, 12, 2), + /* 010 */ V(10, 13, 3), + /* 011 */ V(13, 10, 3), + /* 100 */ V(7, 14, 3), + /* 101 */ V(10, 12, 3), + /* 110 */ V(12, 10, 2), + /* 111 */ V(12, 10, 2), + + /* 0000 0110 1111 ... */ + /* 000 */ V(12, 9, 3), /* 326 */ + /* 001 */ V(7, 13, 3), + /* 010 */ V(5, 14, 2), + /* 011 */ V(5, 14, 2), + /* 100 */ V(11, 13, 1), + /* 101 */ V(11, 13, 1), + /* 110 */ V(11, 13, 1), + /* 111 */ V(11, 13, 1), + + /* 0000 1011 0000 ... */ + /* 00 */ V(9, 14, 1), /* 334 */ + /* 01 */ V(9, 14, 1), + /* 10 */ V(11, 12, 2), + /* 11 */ V(12, 11, 2), + + /* 0000 1011 0001 ... */ + /* 00 */ V(8, 14, 2), /* 338 */ + /* 01 */ V(14, 8, 2), + /* 10 */ V(9, 13, 2), + /* 11 */ V(14, 7, 2), + + /* 0000 1011 0010 ... */ + /* 00 */ V(11, 11, 2), /* 342 */ + /* 01 */ V(8, 13, 2), + /* 10 */ V(13, 8, 2), + /* 11 */ V(6, 14, 2), + + /* 0000 1011 0011 ... */ + /* 0 */ V(14, 6, 1), /* 346 */ + /* 1 */ V(9, 12, 1), + + /* 0000 1011 0100 ... */ + /* 00 */ V(10, 11, 2), /* 348 */ + /* 01 */ V(11, 10, 2), + /* 10 */ V(14, 5, 2), + /* 11 */ V(13, 7, 2), + + /* 0000 1011 0101 ... */ + /* 00 */ V(4, 14, 1), /* 352 */ + /* 01 */ V(4, 14, 1), + /* 10 */ V(14, 4, 2), + /* 11 */ V(8, 12, 2), + + /* 0000 1011 0110 ... */ + /* 0 */ V(12, 8, 1), /* 356 */ + /* 1 */ V(3, 14, 1), + + /* 0000 1011 0111 ... */ + /* 00 */ V(6, 13, 1), /* 358 */ + /* 01 */ V(6, 13, 1), + /* 10 */ V(13, 6, 2), + /* 11 */ V(9, 11, 2), + + /* 0000 1011 1000 ... */ + /* 00 */ V(11, 9, 2), /* 362 */ + /* 01 */ V(10, 10, 2), + /* 10 */ V(14, 1, 1), + /* 11 */ V(14, 1, 1), + + /* 0000 1011 1001 ... */ + /* 00 */ V(13, 4, 1), /* 366 */ + /* 01 */ V(13, 4, 1), + /* 10 */ V(11, 8, 2), + /* 11 */ V(10, 9, 2), + + /* 0000 1011 1010 ... */ + /* 00 */ V(7, 11, 1), /* 370 */ + /* 01 */ V(7, 11, 1), + /* 10 */ V(11, 7, 2), + /* 11 */ V(13, 0, 2), + + /* 0000 1011 1100 ... */ + /* 0 */ V(0, 14, 1), /* 374 */ + /* 1 */ V(14, 0, 1), + + /* 0000 1011 1101 ... */ + /* 0 */ V(5, 13, 1), /* 376 */ + /* 1 */ V(13, 5, 1), + + /* 0000 1011 1110 ... */ + /* 0 */ V(7, 12, 1), /* 378 */ + /* 1 */ V(12, 7, 1), + + /* 0000 1011 1111 ... */ + /* 0 */ V(4, 13, 1), /* 380 */ + /* 1 */ V(8, 11, 1), + + /* 0000 1100 0000 ... */ + /* 0 */ V(9, 10, 1), /* 382 */ + /* 1 */ V(6, 12, 1), + + /* 0000 1100 0001 ... */ + /* 0 */ V(12, 6, 1), /* 384 */ + /* 1 */ V(3, 13, 1), + + /* 0000 1100 0010 ... */ + /* 0 */ V(5, 12, 1), /* 386 */ + /* 1 */ V(12, 5, 1), + + /* 0000 1100 0100 ... */ + /* 0 */ V(8, 10, 1), /* 388 */ + /* 1 */ V(10, 8, 1), + + /* 0000 1100 0101 ... */ + /* 0 */ V(9, 9, 1), /* 390 */ + /* 1 */ V(4, 12, 1), + + /* 0000 1100 0110 ... */ + /* 0 */ V(11, 6, 1), /* 392 */ + /* 1 */ V(7, 10, 1), + + /* 0000 1100 1000 ... */ + /* 0 */ V(5, 11, 1), /* 394 */ + /* 1 */ V(8, 9, 1), + + /* 0000 1100 1011 ... */ + /* 0 */ V(9, 8, 1), /* 396 */ + /* 1 */ V(7, 9, 1), + + /* 0000 1101 0101 ... */ + /* 0 */ V(9, 7, 1), /* 398 */ + /* 1 */ V(8, 8, 1), + + /* 0000 0110 1100 0001 ... */ + /* 0 */ V(14, 12, 1), /* 400 */ + /* 1 */ V(13, 13, 1) +}; + +static +union huffpair const hufftab24[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ V(15, 15, 4), + /* 0100 */ PTR(64, 4), + /* 0101 */ PTR(80, 4), + /* 0110 */ PTR(96, 4), + /* 0111 */ PTR(112, 4), + /* 1000 */ PTR(128, 4), + /* 1001 */ PTR(144, 4), + /* 1010 */ PTR(160, 3), + /* 1011 */ PTR(168, 2), + /* 1100 */ V(1, 1, 4), + /* 1101 */ V(0, 1, 4), + /* 1110 */ V(1, 0, 4), + /* 1111 */ V(0, 0, 4), + + /* 0000 ... */ + /* 0000 */ V(14, 15, 4), /* 16 */ + /* 0001 */ V(15, 14, 4), + /* 0010 */ V(13, 15, 4), + /* 0011 */ V(15, 13, 4), + /* 0100 */ V(12, 15, 4), + /* 0101 */ V(15, 12, 4), + /* 0110 */ V(11, 15, 4), + /* 0111 */ V(15, 11, 4), + /* 1000 */ V(15, 10, 3), + /* 1001 */ V(15, 10, 3), + /* 1010 */ V(10, 15, 4), + /* 1011 */ V(9, 15, 4), + /* 1100 */ V(15, 9, 3), + /* 1101 */ V(15, 9, 3), + /* 1110 */ V(15, 8, 3), + /* 1111 */ V(15, 8, 3), + + /* 0001 ... */ + /* 0000 */ V(8, 15, 4), /* 32 */ + /* 0001 */ V(7, 15, 4), + /* 0010 */ V(15, 7, 3), + /* 0011 */ V(15, 7, 3), + /* 0100 */ V(6, 15, 3), + /* 0101 */ V(6, 15, 3), + /* 0110 */ V(15, 6, 3), + /* 0111 */ V(15, 6, 3), + /* 1000 */ V(5, 15, 3), + /* 1001 */ V(5, 15, 3), + /* 1010 */ V(15, 5, 3), + /* 1011 */ V(15, 5, 3), + /* 1100 */ V(4, 15, 3), + /* 1101 */ V(4, 15, 3), + /* 1110 */ V(15, 4, 3), + /* 1111 */ V(15, 4, 3), + + /* 0010 ... */ + /* 0000 */ V(3, 15, 3), /* 48 */ + /* 0001 */ V(3, 15, 3), + /* 0010 */ V(15, 3, 3), + /* 0011 */ V(15, 3, 3), + /* 0100 */ V(2, 15, 3), + /* 0101 */ V(2, 15, 3), + /* 0110 */ V(15, 2, 3), + /* 0111 */ V(15, 2, 3), + /* 1000 */ V(15, 1, 3), + /* 1001 */ V(15, 1, 3), + /* 1010 */ V(1, 15, 4), + /* 1011 */ V(15, 0, 4), + /* 1100 */ PTR(172, 3), + /* 1101 */ PTR(180, 3), + /* 1110 */ PTR(188, 3), + /* 1111 */ PTR(196, 3), + + /* 0100 ... */ + /* 0000 */ PTR(204, 4), /* 64 */ + /* 0001 */ PTR(220, 3), + /* 0010 */ PTR(228, 3), + /* 0011 */ PTR(236, 3), + /* 0100 */ PTR(244, 2), + /* 0101 */ PTR(248, 2), + /* 0110 */ PTR(252, 2), + /* 0111 */ PTR(256, 2), + /* 1000 */ PTR(260, 2), + /* 1001 */ PTR(264, 2), + /* 1010 */ PTR(268, 2), + /* 1011 */ PTR(272, 2), + /* 1100 */ PTR(276, 2), + /* 1101 */ PTR(280, 3), + /* 1110 */ PTR(288, 2), + /* 1111 */ PTR(292, 2), + + /* 0101 ... */ + /* 0000 */ PTR(296, 2), /* 80 */ + /* 0001 */ PTR(300, 3), + /* 0010 */ PTR(308, 2), + /* 0011 */ PTR(312, 3), + /* 0100 */ PTR(320, 1), + /* 0101 */ PTR(322, 2), + /* 0110 */ PTR(326, 2), + /* 0111 */ PTR(330, 1), + /* 1000 */ PTR(332, 2), + /* 1001 */ PTR(336, 1), + /* 1010 */ PTR(338, 1), + /* 1011 */ PTR(340, 1), + /* 1100 */ PTR(342, 1), + /* 1101 */ PTR(344, 1), + /* 1110 */ PTR(346, 1), + /* 1111 */ PTR(348, 1), + + /* 0110 ... */ + /* 0000 */ PTR(350, 1), /* 96 */ + /* 0001 */ PTR(352, 1), + /* 0010 */ PTR(354, 1), + /* 0011 */ PTR(356, 1), + /* 0100 */ PTR(358, 1), + /* 0101 */ PTR(360, 1), + /* 0110 */ PTR(362, 1), + /* 0111 */ PTR(364, 1), + /* 1000 */ PTR(366, 1), + /* 1001 */ PTR(368, 1), + /* 1010 */ PTR(370, 2), + /* 1011 */ PTR(374, 1), + /* 1100 */ PTR(376, 2), + /* 1101 */ V(7, 3, 4), + /* 1110 */ PTR(380, 1), + /* 1111 */ V(7, 2, 4), + + /* 0111 ... */ + /* 0000 */ V(4, 6, 4), /* 112 */ + /* 0001 */ V(6, 4, 4), + /* 0010 */ V(5, 5, 4), + /* 0011 */ V(7, 1, 4), + /* 0100 */ V(3, 6, 4), + /* 0101 */ V(6, 3, 4), + /* 0110 */ V(4, 5, 4), + /* 0111 */ V(5, 4, 4), + /* 1000 */ V(2, 6, 4), + /* 1001 */ V(6, 2, 4), + /* 1010 */ V(1, 6, 4), + /* 1011 */ V(6, 1, 4), + /* 1100 */ PTR(382, 1), + /* 1101 */ V(3, 5, 4), + /* 1110 */ V(5, 3, 4), + /* 1111 */ V(4, 4, 4), + + /* 1000 ... */ + /* 0000 */ V(2, 5, 4), /* 128 */ + /* 0001 */ V(5, 2, 4), + /* 0010 */ V(1, 5, 4), + /* 0011 */ PTR(384, 1), + /* 0100 */ V(5, 1, 3), + /* 0101 */ V(5, 1, 3), + /* 0110 */ V(3, 4, 4), + /* 0111 */ V(4, 3, 4), + /* 1000 */ V(2, 4, 3), + /* 1001 */ V(2, 4, 3), + /* 1010 */ V(4, 2, 3), + /* 1011 */ V(4, 2, 3), + /* 1100 */ V(3, 3, 3), + /* 1101 */ V(3, 3, 3), + /* 1110 */ V(1, 4, 3), + /* 1111 */ V(1, 4, 3), + + /* 1001 ... */ + /* 0000 */ V(4, 1, 3), /* 144 */ + /* 0001 */ V(4, 1, 3), + /* 0010 */ V(0, 4, 4), + /* 0011 */ V(4, 0, 4), + /* 0100 */ V(2, 3, 3), + /* 0101 */ V(2, 3, 3), + /* 0110 */ V(3, 2, 3), + /* 0111 */ V(3, 2, 3), + /* 1000 */ V(1, 3, 2), + /* 1001 */ V(1, 3, 2), + /* 1010 */ V(1, 3, 2), + /* 1011 */ V(1, 3, 2), + /* 1100 */ V(3, 1, 2), + /* 1101 */ V(3, 1, 2), + /* 1110 */ V(3, 1, 2), + /* 1111 */ V(3, 1, 2), + + /* 1010 ... */ + /* 000 */ V(0, 3, 3), /* 160 */ + /* 001 */ V(3, 0, 3), + /* 010 */ V(2, 2, 2), + /* 011 */ V(2, 2, 2), + /* 100 */ V(1, 2, 1), + /* 101 */ V(1, 2, 1), + /* 110 */ V(1, 2, 1), + /* 111 */ V(1, 2, 1), + + /* 1011 ... */ + /* 00 */ V(2, 1, 1), /* 168 */ + /* 01 */ V(2, 1, 1), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0010 1100 ... */ + /* 000 */ V(0, 15, 1), /* 172 */ + /* 001 */ V(0, 15, 1), + /* 010 */ V(0, 15, 1), + /* 011 */ V(0, 15, 1), + /* 100 */ V(14, 14, 3), + /* 101 */ V(13, 14, 3), + /* 110 */ V(14, 13, 3), + /* 111 */ V(12, 14, 3), + + /* 0010 1101 ... */ + /* 000 */ V(14, 12, 3), /* 180 */ + /* 001 */ V(13, 13, 3), + /* 010 */ V(11, 14, 3), + /* 011 */ V(14, 11, 3), + /* 100 */ V(12, 13, 3), + /* 101 */ V(13, 12, 3), + /* 110 */ V(10, 14, 3), + /* 111 */ V(14, 10, 3), + + /* 0010 1110 ... */ + /* 000 */ V(11, 13, 3), /* 188 */ + /* 001 */ V(13, 11, 3), + /* 010 */ V(12, 12, 3), + /* 011 */ V(9, 14, 3), + /* 100 */ V(14, 9, 3), + /* 101 */ V(10, 13, 3), + /* 110 */ V(13, 10, 3), + /* 111 */ V(11, 12, 3), + + /* 0010 1111 ... */ + /* 000 */ V(12, 11, 3), /* 196 */ + /* 001 */ V(8, 14, 3), + /* 010 */ V(14, 8, 3), + /* 011 */ V(9, 13, 3), + /* 100 */ V(13, 9, 3), + /* 101 */ V(7, 14, 3), + /* 110 */ V(14, 7, 3), + /* 111 */ V(10, 12, 3), + + /* 0100 0000 ... */ + /* 0000 */ V(12, 10, 3), /* 204 */ + /* 0001 */ V(12, 10, 3), + /* 0010 */ V(11, 11, 3), + /* 0011 */ V(11, 11, 3), + /* 0100 */ V(8, 13, 3), + /* 0101 */ V(8, 13, 3), + /* 0110 */ V(13, 8, 3), + /* 0111 */ V(13, 8, 3), + /* 1000 */ V(0, 14, 4), + /* 1001 */ V(14, 0, 4), + /* 1010 */ V(0, 13, 3), + /* 1011 */ V(0, 13, 3), + /* 1100 */ V(14, 6, 2), + /* 1101 */ V(14, 6, 2), + /* 1110 */ V(14, 6, 2), + /* 1111 */ V(14, 6, 2), + + /* 0100 0001 ... */ + /* 000 */ V(6, 14, 3), /* 220 */ + /* 001 */ V(9, 12, 3), + /* 010 */ V(12, 9, 2), + /* 011 */ V(12, 9, 2), + /* 100 */ V(5, 14, 2), + /* 101 */ V(5, 14, 2), + /* 110 */ V(11, 10, 2), + /* 111 */ V(11, 10, 2), + + /* 0100 0010 ... */ + /* 000 */ V(14, 5, 2), /* 228 */ + /* 001 */ V(14, 5, 2), + /* 010 */ V(10, 11, 3), + /* 011 */ V(7, 13, 3), + /* 100 */ V(13, 7, 2), + /* 101 */ V(13, 7, 2), + /* 110 */ V(14, 4, 2), + /* 111 */ V(14, 4, 2), + + /* 0100 0011 ... */ + /* 000 */ V(8, 12, 2), /* 236 */ + /* 001 */ V(8, 12, 2), + /* 010 */ V(12, 8, 2), + /* 011 */ V(12, 8, 2), + /* 100 */ V(4, 14, 3), + /* 101 */ V(2, 14, 3), + /* 110 */ V(3, 14, 2), + /* 111 */ V(3, 14, 2), + + /* 0100 0100 ... */ + /* 00 */ V(6, 13, 2), /* 244 */ + /* 01 */ V(13, 6, 2), + /* 10 */ V(14, 3, 2), + /* 11 */ V(9, 11, 2), + + /* 0100 0101 ... */ + /* 00 */ V(11, 9, 2), /* 248 */ + /* 01 */ V(10, 10, 2), + /* 10 */ V(14, 2, 2), + /* 11 */ V(1, 14, 2), + + /* 0100 0110 ... */ + /* 00 */ V(14, 1, 2), /* 252 */ + /* 01 */ V(5, 13, 2), + /* 10 */ V(13, 5, 2), + /* 11 */ V(7, 12, 2), + + /* 0100 0111 ... */ + /* 00 */ V(12, 7, 2), /* 256 */ + /* 01 */ V(4, 13, 2), + /* 10 */ V(8, 11, 2), + /* 11 */ V(11, 8, 2), + + /* 0100 1000 ... */ + /* 00 */ V(13, 4, 2), /* 260 */ + /* 01 */ V(9, 10, 2), + /* 10 */ V(10, 9, 2), + /* 11 */ V(6, 12, 2), + + /* 0100 1001 ... */ + /* 00 */ V(12, 6, 2), /* 264 */ + /* 01 */ V(3, 13, 2), + /* 10 */ V(13, 3, 2), + /* 11 */ V(2, 13, 2), + + /* 0100 1010 ... */ + /* 00 */ V(13, 2, 2), /* 268 */ + /* 01 */ V(1, 13, 2), + /* 10 */ V(7, 11, 2), + /* 11 */ V(11, 7, 2), + + /* 0100 1011 ... */ + /* 00 */ V(13, 1, 2), /* 272 */ + /* 01 */ V(5, 12, 2), + /* 10 */ V(12, 5, 2), + /* 11 */ V(8, 10, 2), + + /* 0100 1100 ... */ + /* 00 */ V(10, 8, 2), /* 276 */ + /* 01 */ V(9, 9, 2), + /* 10 */ V(4, 12, 2), + /* 11 */ V(12, 4, 2), + + /* 0100 1101 ... */ + /* 000 */ V(6, 11, 2), /* 280 */ + /* 001 */ V(6, 11, 2), + /* 010 */ V(11, 6, 2), + /* 011 */ V(11, 6, 2), + /* 100 */ V(13, 0, 3), + /* 101 */ V(0, 12, 3), + /* 110 */ V(3, 12, 2), + /* 111 */ V(3, 12, 2), + + /* 0100 1110 ... */ + /* 00 */ V(12, 3, 2), /* 288 */ + /* 01 */ V(7, 10, 2), + /* 10 */ V(10, 7, 2), + /* 11 */ V(2, 12, 2), + + /* 0100 1111 ... */ + /* 00 */ V(12, 2, 2), /* 292 */ + /* 01 */ V(5, 11, 2), + /* 10 */ V(11, 5, 2), + /* 11 */ V(1, 12, 2), + + /* 0101 0000 ... */ + /* 00 */ V(8, 9, 2), /* 296 */ + /* 01 */ V(9, 8, 2), + /* 10 */ V(12, 1, 2), + /* 11 */ V(4, 11, 2), + + /* 0101 0001 ... */ + /* 000 */ V(12, 0, 3), /* 300 */ + /* 001 */ V(0, 11, 3), + /* 010 */ V(3, 11, 2), + /* 011 */ V(3, 11, 2), + /* 100 */ V(11, 0, 3), + /* 101 */ V(0, 10, 3), + /* 110 */ V(1, 10, 2), + /* 111 */ V(1, 10, 2), + + /* 0101 0010 ... */ + /* 00 */ V(11, 4, 1), /* 308 */ + /* 01 */ V(11, 4, 1), + /* 10 */ V(6, 10, 2), + /* 11 */ V(10, 6, 2), + + /* 0101 0011 ... */ + /* 000 */ V(7, 9, 2), /* 312 */ + /* 001 */ V(7, 9, 2), + /* 010 */ V(9, 7, 2), + /* 011 */ V(9, 7, 2), + /* 100 */ V(10, 0, 3), + /* 101 */ V(0, 9, 3), + /* 110 */ V(9, 0, 2), + /* 111 */ V(9, 0, 2), + + /* 0101 0100 ... */ + /* 0 */ V(11, 3, 1), /* 320 */ + /* 1 */ V(8, 8, 1), + + /* 0101 0101 ... */ + /* 00 */ V(2, 11, 2), /* 322 */ + /* 01 */ V(5, 10, 2), + /* 10 */ V(11, 2, 1), + /* 11 */ V(11, 2, 1), + + /* 0101 0110 ... */ + /* 00 */ V(10, 5, 2), /* 326 */ + /* 01 */ V(1, 11, 2), + /* 10 */ V(11, 1, 2), + /* 11 */ V(6, 9, 2), + + /* 0101 0111 ... */ + /* 0 */ V(9, 6, 1), /* 330 */ + /* 1 */ V(10, 4, 1), + + /* 0101 1000 ... */ + /* 00 */ V(4, 10, 2), /* 332 */ + /* 01 */ V(7, 8, 2), + /* 10 */ V(8, 7, 1), + /* 11 */ V(8, 7, 1), + + /* 0101 1001 ... */ + /* 0 */ V(3, 10, 1), /* 336 */ + /* 1 */ V(10, 3, 1), + + /* 0101 1010 ... */ + /* 0 */ V(5, 9, 1), /* 338 */ + /* 1 */ V(9, 5, 1), + + /* 0101 1011 ... */ + /* 0 */ V(2, 10, 1), /* 340 */ + /* 1 */ V(10, 2, 1), + + /* 0101 1100 ... */ + /* 0 */ V(10, 1, 1), /* 342 */ + /* 1 */ V(6, 8, 1), + + /* 0101 1101 ... */ + /* 0 */ V(8, 6, 1), /* 344 */ + /* 1 */ V(7, 7, 1), + + /* 0101 1110 ... */ + /* 0 */ V(4, 9, 1), /* 346 */ + /* 1 */ V(9, 4, 1), + + /* 0101 1111 ... */ + /* 0 */ V(3, 9, 1), /* 348 */ + /* 1 */ V(9, 3, 1), + + /* 0110 0000 ... */ + /* 0 */ V(5, 8, 1), /* 350 */ + /* 1 */ V(8, 5, 1), + + /* 0110 0001 ... */ + /* 0 */ V(2, 9, 1), /* 352 */ + /* 1 */ V(6, 7, 1), + + /* 0110 0010 ... */ + /* 0 */ V(7, 6, 1), /* 354 */ + /* 1 */ V(9, 2, 1), + + /* 0110 0011 ... */ + /* 0 */ V(1, 9, 1), /* 356 */ + /* 1 */ V(9, 1, 1), + + /* 0110 0100 ... */ + /* 0 */ V(4, 8, 1), /* 358 */ + /* 1 */ V(8, 4, 1), + + /* 0110 0101 ... */ + /* 0 */ V(5, 7, 1), /* 360 */ + /* 1 */ V(7, 5, 1), + + /* 0110 0110 ... */ + /* 0 */ V(3, 8, 1), /* 362 */ + /* 1 */ V(8, 3, 1), + + /* 0110 0111 ... */ + /* 0 */ V(6, 6, 1), /* 364 */ + /* 1 */ V(2, 8, 1), + + /* 0110 1000 ... */ + /* 0 */ V(8, 2, 1), /* 366 */ + /* 1 */ V(1, 8, 1), + + /* 0110 1001 ... */ + /* 0 */ V(4, 7, 1), /* 368 */ + /* 1 */ V(7, 4, 1), + + /* 0110 1010 ... */ + /* 00 */ V(8, 1, 1), /* 370 */ + /* 01 */ V(8, 1, 1), + /* 10 */ V(0, 8, 2), + /* 11 */ V(8, 0, 2), + + /* 0110 1011 ... */ + /* 0 */ V(5, 6, 1), /* 374 */ + /* 1 */ V(6, 5, 1), + + /* 0110 1100 ... */ + /* 00 */ V(1, 7, 1), /* 376 */ + /* 01 */ V(1, 7, 1), + /* 10 */ V(0, 7, 2), + /* 11 */ V(7, 0, 2), + + /* 0110 1110 ... */ + /* 0 */ V(3, 7, 1), /* 380 */ + /* 1 */ V(2, 7, 1), + + /* 0111 1100 ... */ + /* 0 */ V(0, 6, 1), /* 382 */ + /* 1 */ V(6, 0, 1), + + /* 1000 0011 ... */ + /* 0 */ V(0, 5, 1), /* 384 */ + /* 1 */ V(5, 0, 1) +}; + +# undef V +# undef PTR + +/* external tables */ + +union huffquad const *const mad_huff_quad_table[2] = { hufftabA, hufftabB }; + +struct hufftable const mad_huff_pair_table[32] = { + /* 0 */ { hufftab0, 0, 0 }, + /* 1 */ { hufftab1, 0, 3 }, + /* 2 */ { hufftab2, 0, 3 }, + /* 3 */ { hufftab3, 0, 3 }, + /* 4 */ { 0 /* not used */ }, + /* 5 */ { hufftab5, 0, 3 }, + /* 6 */ { hufftab6, 0, 4 }, + /* 7 */ { hufftab7, 0, 4 }, + /* 8 */ { hufftab8, 0, 4 }, + /* 9 */ { hufftab9, 0, 4 }, + /* 10 */ { hufftab10, 0, 4 }, + /* 11 */ { hufftab11, 0, 4 }, + /* 12 */ { hufftab12, 0, 4 }, + /* 13 */ { hufftab13, 0, 4 }, + /* 14 */ { 0 /* not used */ }, + /* 15 */ { hufftab15, 0, 4 }, + /* 16 */ { hufftab16, 1, 4 }, + /* 17 */ { hufftab16, 2, 4 }, + /* 18 */ { hufftab16, 3, 4 }, + /* 19 */ { hufftab16, 4, 4 }, + /* 20 */ { hufftab16, 6, 4 }, + /* 21 */ { hufftab16, 8, 4 }, + /* 22 */ { hufftab16, 10, 4 }, + /* 23 */ { hufftab16, 13, 4 }, + /* 24 */ { hufftab24, 4, 4 }, + /* 25 */ { hufftab24, 5, 4 }, + /* 26 */ { hufftab24, 6, 4 }, + /* 27 */ { hufftab24, 7, 4 }, + /* 28 */ { hufftab24, 8, 4 }, + /* 29 */ { hufftab24, 9, 4 }, + /* 30 */ { hufftab24, 11, 4 }, + /* 31 */ { hufftab24, 13, 4 } +}; diff --git a/core/multimedia/opieplayer/libmad/huffman.h b/core/multimedia/opieplayer/libmad/huffman.h new file mode 100644 index 0000000..1801210 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/huffman.h @@ -0,0 +1,66 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_HUFFMAN_H +# define LIBMAD_HUFFMAN_H + +union huffquad { + struct { + unsigned short final : 1; + unsigned short hlen : 3; + unsigned short v : 1; + unsigned short w : 1; + unsigned short x : 1; + unsigned short y : 1; + } value; + struct { + unsigned short final : 1; + unsigned short bits : 3; + unsigned short offset : 12; + } ptr; + unsigned short final : 1; +}; + +union huffpair { + struct { + unsigned short final : 1; + unsigned short hlen : 3; + unsigned short x : 4; + unsigned short y : 4; + } value; + struct { + unsigned short final : 1; + unsigned short bits : 3; + unsigned short offset : 12; + } ptr; + unsigned short final : 1; +}; + +struct hufftable { + union huffpair const *table; + unsigned short linbits; + unsigned short startbits; +}; + +extern union huffquad const *const mad_huff_quad_table[2]; +extern struct hufftable const mad_huff_pair_table[32]; + +# endif diff --git a/core/multimedia/opieplayer/libmad/imdct_l_arm.S b/core/multimedia/opieplayer/libmad/imdct_l_arm.S new file mode 100644 index 0000000..b86ba11 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/imdct_l_arm.S @@ -0,0 +1,1000 @@ +/***************************************************************************** +* Copyright (C) 2000-2001 Andre McCurdy +* +* 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 +* +***************************************************************************** +* +* Notes: +* +* +***************************************************************************** +* +* $Id$ +* +* 2001/03/24: Andre McCurdy +* - Corrected PIC unsafe loading of address of 'imdct36_long_karray' +* +* 2000/09/20: Robert Leslie +* - Added a global symbol with leading underscore per suggestion of +* Simon Burge to support linking with the a.out format. +* +* 2000/09/15: Robert Leslie +* - Fixed a small bug where flags were changed before a conditional branch. +* +* 2000/09/15: Andre McCurdy +* - Applied Nicolas Pitre's rounding optimisation in all remaining places. +* +* 2000/09/09: Nicolas Pitre +* - Optimized rounding + scaling operations. +* +* 2000/08/09: Andre McCurdy +* - Original created. +* +****************************************************************************/ + + +/* + On entry: + + r0 = pointer to 18 element input array + r1 = pointer to 36 element output array + r2 = windowing block type + + + Stack frame created during execution of the function: + + Initial Holds: + Stack + pointer + minus: + + 0 + 4 lr + 8 r11 + 12 r10 + 16 r9 + 20 r8 + 24 r7 + 28 r6 + 32 r5 + 36 r4 + + 40 r2 : windowing block type + + 44 ct00 high + 48 ct00 low + 52 ct01 high + 56 ct01 low + 60 ct04 high + 64 ct04 low + 68 ct06 high + 72 ct06 low + 76 ct05 high + 80 ct05 low + 84 ct03 high + 88 ct03 low + 92 -ct05 high + 96 -ct05 low + 100 -ct07 high + 104 -ct07 low + 108 ct07 high + 112 ct07 low + 116 ct02 high + 120 ct02 low +*/ + +#define BLOCK_MODE_NORMAL 0 +#define BLOCK_MODE_START 1 +#define BLOCK_MODE_STOP 3 + + +#define X0 0x00 +#define X1 0x04 +#define X2 0x08 +#define X3 0x0C +#define X4 0x10 +#define X5 0x14 +#define X6 0x18 +#define X7 0x1c +#define X8 0x20 +#define X9 0x24 +#define X10 0x28 +#define X11 0x2c +#define X12 0x30 +#define X13 0x34 +#define X14 0x38 +#define X15 0x3c +#define X16 0x40 +#define X17 0x44 + +#define x0 0x00 +#define x1 0x04 +#define x2 0x08 +#define x3 0x0C +#define x4 0x10 +#define x5 0x14 +#define x6 0x18 +#define x7 0x1c +#define x8 0x20 +#define x9 0x24 +#define x10 0x28 +#define x11 0x2c +#define x12 0x30 +#define x13 0x34 +#define x14 0x38 +#define x15 0x3c +#define x16 0x40 +#define x17 0x44 +#define x18 0x48 +#define x19 0x4c +#define x20 0x50 +#define x21 0x54 +#define x22 0x58 +#define x23 0x5c +#define x24 0x60 +#define x25 0x64 +#define x26 0x68 +#define x27 0x6c +#define x28 0x70 +#define x29 0x74 +#define x30 0x78 +#define x31 0x7c +#define x32 0x80 +#define x33 0x84 +#define x34 0x88 +#define x35 0x8c + +#define K00 0x0ffc19fd +#define K01 0x00b2aa3e +#define K02 0x0fdcf549 +#define K03 0x0216a2a2 +#define K04 0x0f9ee890 +#define K05 0x03768962 +#define K06 0x0f426cb5 +#define K07 0x04cfb0e2 +#define K08 0x0ec835e8 +#define K09 0x061f78aa +#define K10 0x0e313245 +#define K11 0x07635284 +#define K12 0x0d7e8807 +#define K13 0x0898c779 +#define K14 0x0cb19346 +#define K15 0x09bd7ca0 +#define K16 0x0bcbe352 +#define K17 0x0acf37ad + +#define minus_K02 0xf0230ab7 + +#define WL0 0x00b2aa3e +#define WL1 0x0216a2a2 +#define WL2 0x03768962 +#define WL3 0x04cfb0e2 +#define WL4 0x061f78aa +#define WL5 0x07635284 +#define WL6 0x0898c779 +#define WL7 0x09bd7ca0 +#define WL8 0x0acf37ad +#define WL9 0x0bcbe352 +#define WL10 0x0cb19346 +#define WL11 0x0d7e8807 +#define WL12 0x0e313245 +#define WL13 0x0ec835e8 +#define WL14 0x0f426cb5 +#define WL15 0x0f9ee890 +#define WL16 0x0fdcf549 +#define WL17 0x0ffc19fd + + +@***************************************************************************** + + + .text + .align + + .global III_imdct_l + .global _III_imdct_l + +III_imdct_l: +_III_imdct_l: + + stmdb sp!, { r2, r4 - r11, lr } @ all callee saved regs, plus arg3 + + ldr r4, =K08 @ r4 = K08 + ldr r5, =K09 @ r5 = K09 + ldr r8, [r0, #X4] @ r8 = X4 + ldr r9, [r0, #X13] @ r9 = X13 + rsb r6, r4, #0 @ r6 = -K08 + rsb r7, r5, #0 @ r7 = -K09 + + smull r2, r3, r4, r8 @ r2..r3 = (X4 * K08) + smlal r2, r3, r5, r9 @ r2..r3 = (X4 * K08) + (X13 * K09) = ct01 + + smull r10, lr, r8, r5 @ r10..lr = (X4 * K09) + smlal r10, lr, r9, r6 @ r10..lr = (X4 * K09) + (X13 * -K08) = ct00 + + ldr r8, [r0, #X7] @ r8 = X7 + ldr r9, [r0, #X16] @ r9 = X16 + + stmdb sp!, { r2, r3, r10, lr } @ stack ct00_h, ct00_l, ct01_h, ct01_l + + add r8, r8, r9 @ r8 = (X7 + X16) + ldr r9, [r0, #X1] @ r9 = X1 + + smlal r2, r3, r6, r8 @ r2..r3 = ct01 + ((X7 + X16) * -K08) + smlal r2, r3, r7, r9 @ r2..r3 += (X1 * -K09) + + ldr r7, [r0, #X10] @ r7 = X10 + + rsbs r10, r10, #0 + rsc lr, lr, #0 @ r10..lr = -ct00 + + smlal r2, r3, r5, r7 @ r2..r3 += (X10 * K09) = ct06 + + smlal r10, lr, r9, r6 @ r10..lr = -ct00 + ( X1 * -K08) + smlal r10, lr, r8, r5 @ r10..lr += ((X7 + X16) * K09) + smlal r10, lr, r7, r4 @ r10..lr += ( X10 * K08) = ct04 + + stmdb sp!, { r2, r3, r10, lr } @ stack ct04_h, ct04_l, ct06_h, ct06_l + + @---- + + ldr r7, [r0, #X0] + ldr r8, [r0, #X11] + ldr r9, [r0, #X12] + sub r7, r7, r8 + sub r7, r7, r9 @ r7 = (X0 - X11 -X12) = ct14 + + ldr r9, [r0, #X3] + ldr r8, [r0, #X8] + ldr r11, [r0, #X15] + sub r8, r8, r9 + add r8, r8, r11 @ r8 = (X8 - X3 + X15) = ct16 + + add r11, r7, r8 @ r11 = ct14 + ct16 = ct18 + + smlal r2, r3, r6, r11 @ r2..r3 = ct06 + ((X0 - X11 - X3 + X15 + X8 - X12) * -K08) + + ldr r6, [r0, #X2] + ldr r9, [r0, #X9] + ldr r12, [r0, #X14] + sub r6, r6, r9 + sub r6, r6, r12 @ r6 = (X2 - X9 - X14) = ct15 + + ldr r9, [r0, #X5] + ldr r12, [r0, #X6] + sub r9, r9, r12 + ldr r12, [r0, #X17] + sub r9, r9, r12 @ r9 = (X5 - X6 - X17) = ct17 + + add r12, r9, r6 @ r12 = ct15 + ct17 = ct19 + + smlal r2, r3, r5, r12 @ r2..r3 += ((X2 - X9 + X5 - X6 - X17 - X14) * K09) + + smlal r10, lr, r11, r5 @ r10..lr = ct04 + (ct18 * K09) + smlal r10, lr, r12, r4 @ r10..lr = ct04 + (ct18 * K09) + (ct19 * K08) + + movs r2, r2, lsr #28 + adc r2, r2, r3, lsl #4 @ r2 = bits[59..28] of r2..r3 + str r2, [r1, #x22] @ store result x22 + + movs r10, r10, lsr #28 + adc r10, r10, lr, lsl #4 @ r10 = bits[59..28] of r10..lr + str r10, [r1, #x4] @ store result x4 + + @---- + + ldmia sp, { r2, r3, r4, r5 } @ r2..r3 = ct06, r4..r5 = ct04 (dont update sp) + + @ r2..r3 = ct06 + @ r4..r5 = ct04 + @ r6 = ct15 + @ r7 = ct14 + @ r8 = ct16 + @ r9 = ct17 + @ r10 = . + @ r11 = . + @ r12 = . + @ lr = . + + ldr r10, =K03 @ r10 = K03 + ldr lr, =K15 @ lr = K15 + + smlal r2, r3, r10, r7 @ r2..r3 = ct06 + (ct14 * K03) + smlal r4, r5, lr, r7 @ r4..r5 = ct04 + (ct14 * K15) + + ldr r12, =K14 @ r12 = K14 + rsb r10, r10, #0 @ r10 = -K03 + + smlal r2, r3, lr, r6 @ r2..r3 += (ct15 * K15) + smlal r4, r5, r10, r6 @ r4..r5 += (ct15 * -K03) + smlal r2, r3, r12, r8 @ r2..r3 += (ct16 * K14) + + ldr r11, =minus_K02 @ r11 = -K02 + rsb r12, r12, #0 @ r12 = -K14 + + smlal r4, r5, r12, r9 @ r4..r5 += (ct17 * -K14) + smlal r2, r3, r11, r9 @ r2..r3 += (ct17 * -K02) + smlal r4, r5, r11, r8 @ r4..r5 += (ct16 * -K02) + + movs r2, r2, lsr #28 + adc r2, r2, r3, lsl #4 @ r2 = bits[59..28] of r2..r3 + str r2, [r1, #x7] @ store result x7 + + movs r4, r4, lsr #28 + adc r4, r4, r5, lsl #4 @ r4 = bits[59..28] of r4..r5 + str r4, [r1, #x1] @ store result x1 + + @---- + + ldmia sp, { r2, r3, r4, r5 } @ r2..r3 = ct06, r4..r5 = ct04 (dont update sp) + + @ r2..r3 = ct06 + @ r4..r5 = ct04 + @ r6 = ct15 + @ r7 = ct14 + @ r8 = ct16 + @ r9 = ct17 + @ r10 = -K03 + @ r11 = -K02 + @ r12 = -K14 + @ lr = K15 + + rsbs r2, r2, #0 + rsc r3, r3, #0 @ r2..r3 = -ct06 + + smlal r2, r3, r12, r7 @ r2..r3 = -ct06 + (ct14 * -K14) + smlal r2, r3, r10, r8 @ r2..r3 += (ct16 * -K03) + + smlal r4, r5, r12, r6 @ r4..r5 = ct04 + (ct15 * -K14) + smlal r4, r5, r10, r9 @ r4..r5 += (ct17 * -K03) + smlal r4, r5, lr, r8 @ r4..r5 += (ct16 * K15) + smlal r4, r5, r11, r7 @ r4..r5 += (ct14 * -K02) + + rsb lr, lr, #0 @ lr = -K15 + rsb r11, r11, #0 @ r11 = K02 + + smlal r2, r3, lr, r9 @ r2..r3 += (ct17 * -K15) + smlal r2, r3, r11, r6 @ r2..r3 += (ct15 * K02) + + movs r4, r4, lsr #28 + adc r4, r4, r5, lsl #4 @ r4 = bits[59..28] of r4..r5 + str r4, [r1, #x25] @ store result x25 + + movs r2, r2, lsr #28 + adc r2, r2, r3, lsl #4 @ r2 = bits[59..28] of r2..r3 + str r2, [r1, #x19] @ store result x19 + + @---- + + ldr r2, [sp, #16] @ r2 = ct01_l + ldr r3, [sp, #20] @ r3 = ct01_h + + ldr r6, [r0, #X1] + ldr r8, [r0, #X7] + ldr r9, [r0, #X10] + ldr r7, [r0, #X16] + + rsbs r2, r2, #0 + rsc r3, r3, #0 @ r2..r3 = -ct01 + + mov r4, r2 + mov r5, r3 @ r4..r5 = -ct01 + + @ r2..r3 = -ct01 + @ r4..r5 = -ct01 + @ r6 = X1 + @ r7 = X16 + @ r8 = X7 + @ r9 = X10 + @ r10 = -K03 + @ r11 = K02 + @ r12 = -K14 + @ lr = -K15 + + smlal r4, r5, r12, r7 @ r4..r5 = -ct01 + (X16 * -K14) + smlal r2, r3, lr, r9 @ r2..r3 = -ct01 + (X10 * -K15) + + smlal r4, r5, r10, r8 @ r4..r5 += (X7 * -K03) + smlal r2, r3, r10, r7 @ r2..r3 += (X16 * -K03) + + smlal r4, r5, r11, r9 @ r4..r5 += (X10 * K02) + smlal r2, r3, r12, r8 @ r2..r3 += (X7 * -K14) + + rsb lr, lr, #0 @ lr = K15 + rsb r11, r11, #0 @ r11 = -K02 + + smlal r4, r5, lr, r6 @ r4..r5 += (X1 * K15) = ct05 + smlal r2, r3, r11, r6 @ r2..r3 += (X1 * -K02) = ct03 + + stmdb sp!, { r2, r3, r4, r5 } @ stack ct05_h, ct05_l, ct03_h, ct03_l + + rsbs r4, r4, #0 + rsc r5, r5, #0 @ r4..r5 = -ct05 + + stmdb sp!, { r4, r5 } @ stack -ct05_h, -ct05_l + + ldr r2, [sp, #48] @ r2 = ct00_l + ldr r3, [sp, #52] @ r3 = ct00_h + + rsb r10, r10, #0 @ r10 = K03 + + rsbs r4, r2, #0 + rsc r5, r3, #0 @ r4..r5 = -ct00 + + @ r2..r3 = ct00 + @ r4..r5 = -ct00 + @ r6 = X1 + @ r7 = X16 + @ r8 = X7 + @ r9 = X10 + @ r10 = K03 + @ r11 = -K02 + @ r12 = -K14 + @ lr = K15 + + smlal r4, r5, r10, r6 @ r4..r5 = -ct00 + (X1 * K03) + smlal r2, r3, r10, r9 @ r2..r3 = ct00 + (X10 * K03) + + smlal r4, r5, r12, r9 @ r4..r5 += (X10 * -K14) + smlal r2, r3, r12, r6 @ r2..r3 += (X1 * -K14) + + smlal r4, r5, r11, r7 @ r4..r5 += (X16 * -K02) + smlal r4, r5, lr, r8 @ r4..r5 += (X7 * K15) = ct07 + + rsb lr, lr, #0 @ lr = -K15 + rsb r11, r11, #0 @ r11 = K02 + + smlal r2, r3, r11, r8 @ r2..r3 += (X7 * K02) + smlal r2, r3, lr, r7 @ r2..r3 += (X16 * -K15) = ct02 + + rsbs r6, r4, #0 + rsc r7, r5, #0 @ r6..r7 = -ct07 + + stmdb sp!, { r2 - r7 } @ stack -ct07_h, -ct07_l, ct07_h, ct07_l, ct02_h, ct02_l + + + @---- + + add r2, pc, #(imdct36_long_karray-.-8) @ r2 = base address of Knn array (PIC safe ?) + + +loop: + ldr r12, [r0, #X0] + + ldmia r2!, { r5 - r11 } @ first 7 words from Karray element + + smull r3, r4, r5, r12 @ sum = (Kxx * X0) + ldr r12, [r0, #X2] + ldr r5, [r0, #X3] + smlal r3, r4, r6, r12 @ sum += (Kxx * X2) + ldr r12, [r0, #X5] + ldr r6, [r0, #X6] + smlal r3, r4, r7, r5 @ sum += (Kxx * X3) + smlal r3, r4, r8, r12 @ sum += (Kxx * X5) + ldr r12, [r0, #X8] + ldr r5, [r0, #X9] + smlal r3, r4, r9, r6 @ sum += (Kxx * X6) + smlal r3, r4, r10, r12 @ sum += (Kxx * X8) + smlal r3, r4, r11, r5 @ sum += (Kxx * X9) + + ldmia r2!, { r5 - r10 } @ final 6 words from Karray element + + ldr r11, [r0, #X11] + ldr r12, [r0, #X12] + smlal r3, r4, r5, r11 @ sum += (Kxx * X11) + ldr r11, [r0, #X14] + ldr r5, [r0, #X15] + smlal r3, r4, r6, r12 @ sum += (Kxx * X12) + smlal r3, r4, r7, r11 @ sum += (Kxx * X14) + ldr r11, [r0, #X17] + smlal r3, r4, r8, r5 @ sum += (Kxx * X15) + smlal r3, r4, r9, r11 @ sum += (Kxx * X17) + + add r5, sp, r10, lsr #16 @ create index back into stack for required ctxx + + ldmia r5, { r6, r7 } @ r6..r7 = ctxx + + mov r8, r10, lsl #16 @ push ctxx index off the top end + + adds r3, r3, r6 @ add low words + adc r4, r4, r7 @ add high words, with carry + movs r3, r3, lsr #28 + adc r3, r3, r4, lsl #4 @ r3 = bits[59..28] of r3..r4 + + str r3, [r1, r8, lsr #24] @ push completion flag off the bottom end + + movs r8, r8, lsl #8 @ push result location index off the top end + beq loop @ loop back if completion flag not set + b imdct_l_windowing @ branch to windowing stage if looping finished + +imdct36_long_karray: + + .word K17, -K13, K10, -K06, -K05, K01, -K00, K04, -K07, K11, K12, -K16, 0x00000000 + .word K13, K07, K16, K01, K10, -K05, K04, -K11, K00, -K17, K06, -K12, 0x00200800 + .word K11, K17, K05, K12, -K01, K06, -K07, K00, -K13, K04, -K16, K10, 0x00200c00 + .word K07, K00, -K12, K05, -K16, -K10, K11, -K17, K04, K13, K01, K06, 0x00001400 + .word K05, K10, -K00, -K17, K07, -K13, K12, K06, -K16, K01, -K11, -K04, 0x00181800 + .word K01, K05, -K07, -K11, K13, K17, -K16, -K12, K10, K06, -K04, -K00, 0x00102000 + .word -K16, K12, -K11, K07, K04, -K00, -K01, K05, -K06, K10, K13, -K17, 0x00284800 + .word -K12, K06, K17, -K00, -K11, K04, K05, -K10, K01, K16, -K07, -K13, 0x00085000 + .word -K10, K16, K04, -K13, -K00, K07, K06, -K01, -K12, -K05, K17, K11, 0x00105400 + .word -K06, -K01, K13, K04, K17, -K11, -K10, -K16, -K05, K12, K00, K07, 0x00185c00 + .word -K04, -K11, -K01, K16, K06, K12, K13, -K07, -K17, -K00, -K10, -K05, 0x00006000 + .word -K00, -K04, -K06, -K10, -K12, -K16, -K17, -K13, -K11, -K07, -K05, -K01, 0x00206801 + + + @---- + @------------------------------------------------------------------------- + @---- + +imdct_l_windowing: + + ldr r11, [sp, #80] @ fetch function parameter 3 from out of the stack + ldmia r1!, { r0, r2 - r9 } @ load 9 words from x0, update pointer + + @ r0 = x0 + @ r1 = &x[9] + @ r2 = x1 + @ r3 = x2 + @ r4 = x3 + @ r5 = x4 + @ r6 = x5 + @ r7 = x6 + @ r8 = x7 + @ r9 = x8 + @ r10 = . + @ r11 = window mode: (0 == normal), (1 == start block), (3 == stop block) + @ r12 = . + @ lr = . + + cmp r11, #BLOCK_MODE_STOP @ setup flags + rsb r10, r0, #0 @ r10 = -x0 (DONT change flags !!) + beq stop_block_x0_to_x17 + + + @ start and normal blocks are treated the same for x[0]..x[17] + +normal_block_x0_to_x17: + + ldr r12, =WL9 @ r12 = window_l[9] + + rsb r0, r9, #0 @ r0 = -x8 + rsb r9, r2, #0 @ r9 = -x1 + rsb r2, r8, #0 @ r2 = -x7 + rsb r8, r3, #0 @ r8 = -x2 + rsb r3, r7, #0 @ r3 = -x6 + rsb r7, r4, #0 @ r7 = -x3 + rsb r4, r6, #0 @ r4 = -x5 + rsb r6, r5, #0 @ r6 = -x4 + + @ r0 = -x8 + @ r1 = &x[9] + @ r2 = -x7 + @ r3 = -x6 + @ r4 = -x5 + @ r5 = . + @ r6 = -x4 + @ r7 = -x3 + @ r8 = -x2 + @ r9 = -x1 + @ r10 = -x0 + @ r11 = window mode: (0 == normal), (1 == start block), (3 == stop block) + @ r12 = window_l[9] + @ lr = . + + smull r5, lr, r12, r0 @ r5..lr = (window_l[9] * (x[9] == -x[8])) + ldr r12, =WL10 @ r12 = window_l[10] + movs r5, r5, lsr #28 + adc r0, r5, lr, lsl #4 @ r0 = bits[59..28] of windowed x9 + + smull r5, lr, r12, r2 @ r5..lr = (window_l[10] * (x[10] == -x[7])) + ldr r12, =WL11 @ r12 = window_l[11] + movs r5, r5, lsr #28 + adc r2, r5, lr, lsl #4 @ r2 = bits[59..28] of windowed x10 + + smull r5, lr, r12, r3 @ r5..lr = (window_l[11] * (x[11] == -x[6])) + ldr r12, =WL12 @ r12 = window_l[12] + movs r5, r5, lsr #28 + adc r3, r5, lr, lsl #4 @ r3 = bits[59..28] of windowed x11 + + smull r5, lr, r12, r4 @ r5..lr = (window_l[12] * (x[12] == -x[5])) + ldr r12, =WL13 @ r12 = window_l[13] + movs r5, r5, lsr #28 + adc r4, r5, lr, lsl #4 @ r4 = bits[59..28] of windowed x12 + + smull r5, lr, r12, r6 @ r5..lr = (window_l[13] * (x[13] == -x[4])) + ldr r12, =WL14 @ r12 = window_l[14] + movs r5, r5, lsr #28 + adc r6, r5, lr, lsl #4 @ r6 = bits[59..28] of windowed x13 + + smull r5, lr, r12, r7 @ r5..lr = (window_l[14] * (x[14] == -x[3])) + ldr r12, =WL15 @ r12 = window_l[15] + movs r5, r5, lsr #28 + adc r7, r5, lr, lsl #4 @ r7 = bits[59..28] of windowed x14 + + smull r5, lr, r12, r8 @ r5..lr = (window_l[15] * (x[15] == -x[2])) + ldr r12, =WL16 @ r12 = window_l[16] + movs r5, r5, lsr #28 + adc r8, r5, lr, lsl #4 @ r8 = bits[59..28] of windowed x15 + + smull r5, lr, r12, r9 @ r5..lr = (window_l[16] * (x[16] == -x[1])) + ldr r12, =WL17 @ r12 = window_l[17] + movs r5, r5, lsr #28 + adc r9, r5, lr, lsl #4 @ r9 = bits[59..28] of windowed x16 + + smull r5, lr, r12, r10 @ r5..lr = (window_l[17] * (x[17] == -x[0])) + ldr r12, =WL0 @ r12 = window_l[0] + movs r5, r5, lsr #28 + adc r10, r5, lr, lsl #4 @ r10 = bits[59..28] of windowed x17 + + + stmia r1, { r0, r2 - r4, r6 - r10 } @ store windowed x[9] .. x[17] + ldmdb r1!, { r0, r2 - r9 } @ load 9 words downto (and including) x0 + + + smull r10, lr, r12, r0 @ r10..lr = (window_l[0] * x[0]) + ldr r12, =WL1 @ r12 = window_l[1] + movs r10, r10, lsr #28 + adc r0, r10, lr, lsl #4 @ r0 = bits[59..28] of windowed x0 + + smull r10, lr, r12, r2 @ r10..lr = (window_l[1] * x[1]) + ldr r12, =WL2 @ r12 = window_l[2] + movs r10, r10, lsr #28 + adc r2, r10, lr, lsl #4 @ r2 = bits[59..28] of windowed x1 + + smull r10, lr, r12, r3 @ r10..lr = (window_l[2] * x[2]) + ldr r12, =WL3 @ r12 = window_l[3] + movs r10, r10, lsr #28 + adc r3, r10, lr, lsl #4 @ r3 = bits[59..28] of windowed x2 + + smull r10, lr, r12, r4 @ r10..lr = (window_l[3] * x[3]) + ldr r12, =WL4 @ r12 = window_l[4] + movs r10, r10, lsr #28 + adc r4, r10, lr, lsl #4 @ r4 = bits[59..28] of windowed x3 + + smull r10, lr, r12, r5 @ r10..lr = (window_l[4] * x[4]) + ldr r12, =WL5 @ r12 = window_l[5] + movs r10, r10, lsr #28 + adc r5, r10, lr, lsl #4 @ r5 = bits[59..28] of windowed x4 + + smull r10, lr, r12, r6 @ r10..lr = (window_l[5] * x[5]) + ldr r12, =WL6 @ r12 = window_l[6] + movs r10, r10, lsr #28 + adc r6, r10, lr, lsl #4 @ r6 = bits[59..28] of windowed x5 + + smull r10, lr, r12, r7 @ r10..lr = (window_l[6] * x[6]) + ldr r12, =WL7 @ r12 = window_l[7] + movs r10, r10, lsr #28 + adc r7, r10, lr, lsl #4 @ r7 = bits[59..28] of windowed x6 + + smull r10, lr, r12, r8 @ r10..lr = (window_l[7] * x[7]) + ldr r12, =WL8 @ r12 = window_l[8] + movs r10, r10, lsr #28 + adc r8, r10, lr, lsl #4 @ r8 = bits[59..28] of windowed x7 + + smull r10, lr, r12, r9 @ r10..lr = (window_l[8] * x[8]) + movs r10, r10, lsr #28 + adc r9, r10, lr, lsl #4 @ r9 = bits[59..28] of windowed x8 + + stmia r1, { r0, r2 - r9 } @ store windowed x[0] .. x[8] + + cmp r11, #BLOCK_MODE_START + beq start_block_x18_to_x35 + + + @---- + + +normal_block_x18_to_x35: + + ldr r11, =WL3 @ r11 = window_l[3] + ldr r12, =WL4 @ r12 = window_l[4] + + add r1, r1, #(18*4) @ r1 = &x[18] + + ldmia r1!, { r0, r2 - r4, r6 - r10 } @ load 9 words from x18, update pointer + + @ r0 = x18 + @ r1 = &x[27] + @ r2 = x19 + @ r3 = x20 + @ r4 = x21 + @ r5 = . + @ r6 = x22 + @ r7 = x23 + @ r8 = x24 + @ r9 = x25 + @ r10 = x26 + @ r11 = window_l[3] + @ r12 = window_l[4] + @ lr = . + + smull r5, lr, r12, r6 @ r5..lr = (window_l[4] * (x[22] == x[31])) + movs r5, r5, lsr #28 + adc r5, r5, lr, lsl #4 @ r5 = bits[59..28] of windowed x31 + + smull r6, lr, r11, r4 @ r5..lr = (window_l[3] * (x[21] == x[32])) + ldr r12, =WL5 @ r12 = window_l[5] + movs r6, r6, lsr #28 + adc r6, r6, lr, lsl #4 @ r6 = bits[59..28] of windowed x32 + + smull r4, lr, r12, r7 @ r4..lr = (window_l[5] * (x[23] == x[30])) + ldr r11, =WL1 @ r11 = window_l[1] + ldr r12, =WL2 @ r12 = window_l[2] + movs r4, r4, lsr #28 + adc r4, r4, lr, lsl #4 @ r4 = bits[59..28] of windowed x30 + + smull r7, lr, r12, r3 @ r7..lr = (window_l[2] * (x[20] == x[33])) + ldr r12, =WL6 @ r12 = window_l[6] + movs r7, r7, lsr #28 + adc r7, r7, lr, lsl #4 @ r7 = bits[59..28] of windowed x33 + + smull r3, lr, r12, r8 @ r3..lr = (window_l[6] * (x[24] == x[29])) + movs r3, r3, lsr #28 + adc r3, r3, lr, lsl #4 @ r3 = bits[59..28] of windowed x29 + + smull r8, lr, r11, r2 @ r7..lr = (window_l[1] * (x[19] == x[34])) + ldr r12, =WL7 @ r12 = window_l[7] + ldr r11, =WL8 @ r11 = window_l[8] + movs r8, r8, lsr #28 + adc r8, r8, lr, lsl #4 @ r8 = bits[59..28] of windowed x34 + + smull r2, lr, r12, r9 @ r7..lr = (window_l[7] * (x[25] == x[28])) + ldr r12, =WL0 @ r12 = window_l[0] + movs r2, r2, lsr #28 + adc r2, r2, lr, lsl #4 @ r2 = bits[59..28] of windowed x28 + + smull r9, lr, r12, r0 @ r3..lr = (window_l[0] * (x[18] == x[35])) + movs r9, r9, lsr #28 + adc r9, r9, lr, lsl #4 @ r9 = bits[59..28] of windowed x35 + + smull r0, lr, r11, r10 @ r7..lr = (window_l[8] * (x[26] == x[27])) + ldr r11, =WL16 @ r11 = window_l[16] + ldr r12, =WL17 @ r12 = window_l[17] + movs r0, r0, lsr #28 + adc r0, r0, lr, lsl #4 @ r0 = bits[59..28] of windowed x27 + + + stmia r1, { r0, r2 - r9 } @ store windowed x[27] .. x[35] + ldmdb r1!, { r0, r2 - r9 } @ load 9 words downto (and including) x18 + + + smull r10, lr, r12, r0 @ r10..lr = (window_l[17] * x[18]) + movs r10, r10, lsr #28 + adc r0, r10, lr, lsl #4 @ r0 = bits[59..28] of windowed x0 + + smull r10, lr, r11, r2 @ r10..lr = (window_l[16] * x[19]) + ldr r11, =WL14 @ r11 = window_l[14] + ldr r12, =WL15 @ r12 = window_l[15] + movs r10, r10, lsr #28 + adc r2, r10, lr, lsl #4 @ r2 = bits[59..28] of windowed x1 + + smull r10, lr, r12, r3 @ r10..lr = (window_l[15] * x[20]) + movs r10, r10, lsr #28 + adc r3, r10, lr, lsl #4 @ r3 = bits[59..28] of windowed x2 + + smull r10, lr, r11, r4 @ r10..lr = (window_l[14] * x[21]) + ldr r11, =WL12 @ r11 = window_l[12] + ldr r12, =WL13 @ r12 = window_l[13] + movs r10, r10, lsr #28 + adc r4, r10, lr, lsl #4 @ r4 = bits[59..28] of windowed x3 + + smull r10, lr, r12, r5 @ r10..lr = (window_l[13] * x[22]) + movs r10, r10, lsr #28 + adc r5, r10, lr, lsl #4 @ r5 = bits[59..28] of windowed x4 + + smull r10, lr, r11, r6 @ r10..lr = (window_l[12] * x[23]) + ldr r11, =WL10 @ r12 = window_l[10] + ldr r12, =WL11 @ r12 = window_l[11] + movs r10, r10, lsr #28 + adc r6, r10, lr, lsl #4 @ r6 = bits[59..28] of windowed x5 + + smull r10, lr, r12, r7 @ r10..lr = (window_l[11] * x[24]) + movs r10, r10, lsr #28 + adc r7, r10, lr, lsl #4 @ r7 = bits[59..28] of windowed x6 + + smull r10, lr, r11, r8 @ r10..lr = (window_l[10] * x[25]) + ldr r12, =WL9 @ r12 = window_l[9] + movs r10, r10, lsr #28 + adc r8, r10, lr, lsl #4 @ r8 = bits[59..28] of windowed x7 + + smull r10, lr, r12, r9 @ r10..lr = (window_l[9] * x[26]) + + movs r10, r10, lsr #28 + adc r9, r10, lr, lsl #4 @ r9 = bits[59..28] of windowed x8 + + stmia r1, { r0, r2 - r9 } @ store windowed x[18] .. x[26] + + @---- + @ NB there are 2 possible exits from this function - this is only one of them + @---- + + add sp, sp, #(21*4) @ return stack frame + ldmia sp!, { r4 - r11, pc } @ restore callee saved regs, and return + + @---- + + +stop_block_x0_to_x17: + + @ r0 = x0 + @ r1 = &x[9] + @ r2 = x1 + @ r3 = x2 + @ r4 = x3 + @ r5 = x4 + @ r6 = x5 + @ r7 = x6 + @ r8 = x7 + @ r9 = x8 + @ r10 = -x0 + @ r11 = window mode: (0 == normal), (1 == start block), (3 == stop block) + @ r12 = . + @ lr = . + + rsb r0, r6, #0 @ r0 = -x5 + rsb r6, r2, #0 @ r6 = -x1 + rsb r2, r5, #0 @ r2 = -x4 + rsb r5, r3, #0 @ r5 = -x2 + rsb r3, r4, #0 @ r3 = -x3 + + add r1, r1, #(3*4) @ r1 = &x[12] + stmia r1, { r0, r2, r3, r5, r6, r10 } @ store unchanged x[12] .. x[17] + + ldr r0, =WL1 @ r0 = window_l[1] == window_s[0] + + rsb r10, r9, #0 @ r10 = -x8 + rsb r12, r8, #0 @ r12 = -x7 + rsb lr, r7, #0 @ lr = -x6 + + @ r0 = WL1 + @ r1 = &x[12] + @ r2 = . + @ r3 = . + @ r4 = . + @ r5 = . + @ r6 = . + @ r7 = x6 + @ r8 = x7 + @ r9 = x8 + @ r10 = -x8 + @ r11 = window mode: (0 == normal), (1 == start block), (3 == stop block) + @ r12 = -x7 + @ lr = -x6 + + smull r5, r6, r0, r7 @ r5..r6 = (window_l[1] * x[6]) + ldr r2, =WL4 @ r2 = window_l[4] == window_s[1] + movs r5, r5, lsr #28 + adc r7, r5, r6, lsl #4 @ r7 = bits[59..28] of windowed x6 + + smull r5, r6, r2, r8 @ r5..r6 = (window_l[4] * x[7]) + ldr r3, =WL7 @ r3 = window_l[7] == window_s[2] + movs r5, r5, lsr #28 + adc r8, r5, r6, lsl #4 @ r8 = bits[59..28] of windowed x7 + + smull r5, r6, r3, r9 @ r5..r6 = (window_l[7] * x[8]) + ldr r4, =WL10 @ r4 = window_l[10] == window_s[3] + movs r5, r5, lsr #28 + adc r9, r5, r6, lsl #4 @ r9 = bits[59..28] of windowed x8 + + smull r5, r6, r4, r10 @ r5..r6 = (window_l[10] * (x[9] == -x[8])) + ldr r0, =WL13 @ r0 = window_l[13] == window_s[4] + movs r5, r5, lsr #28 + adc r10, r5, r6, lsl #4 @ r10 = bits[59..28] of windowed x9 + + smull r5, r6, r0, r12 @ r5..r6 = (window_l[13] * (x[10] == -x[7])) + ldr r2, =WL16 @ r2 = window_l[16] == window_s[5] + movs r5, r5, lsr #28 + adc r12, r5, r6, lsl #4 @ r10 = bits[59..28] of windowed x9 + + smull r5, r6, r2, lr @ r5..r6 = (window_l[16] * (x[11] == -x[6])) + + ldr r0, =0x00 + + movs r5, r5, lsr #28 + adc lr, r5, r6, lsl #4 @ r10 = bits[59..28] of windowed x9 + + stmdb r1!, { r7 - r10, r12, lr } @ store windowed x[6] .. x[11] + + ldr r5, =0x00 + ldr r6, =0x00 + ldr r2, =0x00 + ldr r3, =0x00 + ldr r4, =0x00 + + stmdb r1!, { r0, r2 - r6 } @ store windowed x[0] .. x[5] + + b normal_block_x18_to_x35 + + + @---- + + +start_block_x18_to_x35: + + ldr r4, =WL1 @ r0 = window_l[1] == window_s[0] + + add r1, r1, #(24*4) @ r1 = &x[24] + + ldmia r1, { r0, r2, r3 } @ load 3 words from x24, dont update pointer + + @ r0 = x24 + @ r1 = &x[24] + @ r2 = x25 + @ r3 = x26 + @ r4 = WL1 + @ r5 = WL4 + @ r6 = WL7 + @ r7 = WL10 + @ r8 = WL13 + @ r9 = WL16 + @ r10 = . + @ r11 = . + @ r12 = . + @ lr = . + + ldr r5, =WL4 @ r5 = window_l[4] == window_s[1] + + smull r10, r11, r4, r0 @ r10..r11 = (window_l[1] * (x[24] == x[29])) + ldr r6, =WL7 @ r6 = window_l[7] == window_s[2] + movs r10, r10, lsr #28 + adc lr, r10, r11, lsl #4 @ lr = bits[59..28] of windowed x29 + + smull r10, r11, r5, r2 @ r10..r11 = (window_l[4] * (x[25] == x[28])) + ldr r7, =WL10 @ r7 = window_l[10] == window_s[3] + movs r10, r10, lsr #28 + adc r12, r10, r11, lsl #4 @ r12 = bits[59..28] of windowed x28 + + smull r10, r11, r6, r3 @ r10..r11 = (window_l[7] * (x[26] == x[27])) + ldr r8, =WL13 @ r8 = window_l[13] == window_s[4] + movs r10, r10, lsr #28 + adc r4, r10, r11, lsl #4 @ r4 = bits[59..28] of windowed x27 + + smull r10, r11, r7, r3 @ r10..r11 = (window_l[10] * x[26]) + ldr r9, =WL16 @ r9 = window_l[16] == window_s[5] + movs r10, r10, lsr #28 + adc r3, r10, r11, lsl #4 @ r3 = bits[59..28] of windowed x26 + + smull r10, r11, r8, r2 @ r10..r11 = (window_l[13] * x[25]) + ldr r5, =0x00 + movs r10, r10, lsr #28 + adc r2, r10, r11, lsl #4 @ r2 = bits[59..28] of windowed x25 + + smull r10, r11, r9, r0 @ r10..r11 = (window_l[16] * x[24]) + ldr r6, =0x00 + movs r10, r10, lsr #28 + adc r0, r10, r11, lsl #4 @ r0 = bits[59..28] of windowed x24 + + stmia r1!, { r0, r2, r3, r4, r12, lr } @ store windowed x[24] .. x[29] + + ldr r7, =0x00 + ldr r8, =0x00 + ldr r9, =0x00 + ldr r10, =0x00 + + stmia r1!, { r5 - r10 } @ store windowed x[30] .. x[35] + + @---- + @ NB there are 2 possible exits from this function - this is only one of them + @---- + + add sp, sp, #(21*4) @ return stack frame + ldmia sp!, { r4 - r11, pc } @ restore callee saved regs, and return + + @---- + @END + @---- + diff --git a/core/multimedia/opieplayer/libmad/imdct_s.dat b/core/multimedia/opieplayer/libmad/imdct_s.dat new file mode 100644 index 0000000..00d62eb --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/imdct_s.dat @@ -0,0 +1,62 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + + /* 0 */ { MAD_F(0x09bd7ca0) /* 0.608761429 */, + -MAD_F(0x0ec835e8) /* -0.923879533 */, + -MAD_F(0x0216a2a2) /* -0.130526192 */, + MAD_F(0x0fdcf549) /* 0.991444861 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + -MAD_F(0x0cb19346) /* -0.793353340 */ }, + + /* 6 */ { -MAD_F(0x0cb19346) /* -0.793353340 */, + MAD_F(0x061f78aa) /* 0.382683432 */, + MAD_F(0x0fdcf549) /* 0.991444861 */, + MAD_F(0x0216a2a2) /* 0.130526192 */, + -MAD_F(0x0ec835e8) /* -0.923879533 */, + -MAD_F(0x09bd7ca0) /* -0.608761429 */ }, + + /* 1 */ { MAD_F(0x061f78aa) /* 0.382683432 */, + -MAD_F(0x0ec835e8) /* -0.923879533 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + MAD_F(0x0ec835e8) /* 0.923879533 */ }, + + /* 7 */ { -MAD_F(0x0ec835e8) /* -0.923879533 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + MAD_F(0x061f78aa) /* 0.382683432 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, + MAD_F(0x061f78aa) /* 0.382683432 */ }, + + /* 2 */ { MAD_F(0x0216a2a2) /* 0.130526192 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + MAD_F(0x09bd7ca0) /* 0.608761429 */, + -MAD_F(0x0cb19346) /* -0.793353340 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, + -MAD_F(0x0fdcf549) /* -0.991444861 */ }, + + /* 8 */ { -MAD_F(0x0fdcf549) /* -0.991444861 */, + -MAD_F(0x0ec835e8) /* -0.923879533 */, + -MAD_F(0x0cb19346) /* -0.793353340 */, + -MAD_F(0x09bd7ca0) /* -0.608761429 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + -MAD_F(0x0216a2a2) /* -0.130526192 */ } diff --git a/core/multimedia/opieplayer/libmad/layer12.c b/core/multimedia/opieplayer/libmad/layer12.c new file mode 100644 index 0000000..41b17ca --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/layer12.c @@ -0,0 +1,496 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifdef HAVE_CONFIG_H +# include "libmad_config.h" +# endif + +# include "libmad_global.h" + +# ifdef HAVE_LIMITS_H +# include +# else +# define CHAR_BIT 8 +# endif + +# include "fixed.h" +# include "bit.h" +# include "stream.h" +# include "frame.h" +# include "layer12.h" + +/* + * scalefactor table + * used in both Layer I and Layer II decoding + */ +static +mad_fixed_t const sf_table[63] = { +# include "sf_table.dat" +}; + +/* --- Layer I ------------------------------------------------------------- */ + +/* linear scaling table */ +static +mad_fixed_t const linear_table[14] = { + MAD_F(0x15555555), /* 2^2 / (2^2 - 1) == 1.33333333333333 */ + MAD_F(0x12492492), /* 2^3 / (2^3 - 1) == 1.14285714285714 */ + MAD_F(0x11111111), /* 2^4 / (2^4 - 1) == 1.06666666666667 */ + MAD_F(0x10842108), /* 2^5 / (2^5 - 1) == 1.03225806451613 */ + MAD_F(0x10410410), /* 2^6 / (2^6 - 1) == 1.01587301587302 */ + MAD_F(0x10204081), /* 2^7 / (2^7 - 1) == 1.00787401574803 */ + MAD_F(0x10101010), /* 2^8 / (2^8 - 1) == 1.00392156862745 */ + MAD_F(0x10080402), /* 2^9 / (2^9 - 1) == 1.00195694716243 */ + MAD_F(0x10040100), /* 2^10 / (2^10 - 1) == 1.00097751710655 */ + MAD_F(0x10020040), /* 2^11 / (2^11 - 1) == 1.00048851978505 */ + MAD_F(0x10010010), /* 2^12 / (2^12 - 1) == 1.00024420024420 */ + MAD_F(0x10008004), /* 2^13 / (2^13 - 1) == 1.00012208521548 */ + MAD_F(0x10004001), /* 2^14 / (2^14 - 1) == 1.00006103888177 */ + MAD_F(0x10002000) /* 2^15 / (2^15 - 1) == 1.00003051850948 */ +}; + +/* + * NAME: I_sample() + * DESCRIPTION: decode one requantized Layer I sample from a bitstream + */ +static +mad_fixed_t I_sample(struct mad_bitptr *ptr, unsigned int nb) +{ + mad_fixed_t sample; + + sample = mad_bit_read(ptr, nb); + + /* invert most significant bit, extend sign, then scale to fixed format */ + + sample ^= 1 << (nb - 1); + sample |= -(sample & (1 << (nb - 1))); + + sample <<= MAD_F_FRACBITS - (nb - 1); + + /* requantize the sample */ + + /* s'' = (2^nb / (2^nb - 1)) * (s''' + 2^(-nb + 1)) */ + + sample += MAD_F_ONE >> (nb - 1); + + return mad_f_mul(sample, linear_table[nb - 2]); + + /* s' = factor * s'' */ + /* (to be performed by caller) */ +} + +/* + * NAME: layer->I() + * DESCRIPTION: decode a single Layer I frame + */ +int mad_layer_I(struct mad_stream *stream, struct mad_frame *frame) +{ + struct mad_header *header = &frame->header; + unsigned int nch, bound, ch, s, sb, nb; + unsigned char allocation[2][32], scalefactor[2][32]; + + nch = MAD_NCHANNELS(header); + + bound = 32; + if (header->mode == MAD_MODE_JOINT_STEREO) { + header->flags |= MAD_FLAG_I_STEREO; + bound = 4 + header->mode_extension * 4; + } + + /* check CRC word */ + + if (header->flags & MAD_FLAG_PROTECTION) { + header->crc_check = + mad_bit_crc(stream->ptr, 4 * (bound * nch + (32 - bound)), + header->crc_check); + + if (header->crc_check != header->crc_target && + !(frame->options & MAD_OPTION_IGNORECRC)) { + stream->error = MAD_ERROR_BADCRC; + return -1; + } + } + + /* decode bit allocations */ + + for (sb = 0; sb < bound; ++sb) { + for (ch = 0; ch < nch; ++ch) { + nb = mad_bit_read(&stream->ptr, 4); + + if (nb == 15) { + stream->error = MAD_ERROR_BADBITALLOC; + return -1; + } + + allocation[ch][sb] = nb ? nb + 1 : 0; + } + } + + for (sb = bound; sb < 32; ++sb) { + nb = mad_bit_read(&stream->ptr, 4); + + if (nb == 15) { + stream->error = MAD_ERROR_BADBITALLOC; + return -1; + } + + allocation[0][sb] = + allocation[1][sb] = nb ? nb + 1 : 0; + } + + /* decode scalefactors */ + + for (sb = 0; sb < 32; ++sb) { + for (ch = 0; ch < nch; ++ch) { + if (allocation[ch][sb]) { + scalefactor[ch][sb] = mad_bit_read(&stream->ptr, 6); + + if (scalefactor[ch][sb] == 63) { + stream->error = MAD_ERROR_BADSCALEFACTOR; + return -1; + } + } + } + } + + /* decode samples */ + + for (s = 0; s < 12; ++s) { + for (sb = 0; sb < bound; ++sb) { + for (ch = 0; ch < nch; ++ch) { + nb = allocation[ch][sb]; + frame->sbsample[ch][s][sb] = nb ? + mad_f_mul(I_sample(&stream->ptr, nb), + sf_table[scalefactor[ch][sb]]) : 0; + } + } + + for (sb = bound; sb < 32; ++sb) { + if ((nb = allocation[0][sb])) { + mad_fixed_t sample; + + sample = I_sample(&stream->ptr, nb); + + for (ch = 0; ch < nch; ++ch) { + frame->sbsample[ch][s][sb] = + mad_f_mul(sample, sf_table[scalefactor[ch][sb]]); + } + } + else { + for (ch = 0; ch < nch; ++ch) + frame->sbsample[ch][s][sb] = 0; + } + } + } + + return 0; +} + +/* --- Layer II ------------------------------------------------------------ */ + +/* possible quantization per subband table */ +static +struct { + unsigned int sblimit; + unsigned char const offsets[30]; +} const sbquant_table[5] = { + /* ISO/IEC 11172-3 Table B.2a */ + { 27, { 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, /* 0 */ + 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 } }, + /* ISO/IEC 11172-3 Table B.2b */ + { 30, { 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, /* 1 */ + 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0 } }, + /* ISO/IEC 11172-3 Table B.2c */ + { 8, { 5, 5, 2, 2, 2, 2, 2, 2 } }, /* 2 */ + /* ISO/IEC 11172-3 Table B.2d */ + { 12, { 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 } }, /* 3 */ + /* ISO/IEC 13818-3 Table B.1 */ + { 30, { 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, /* 4 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } } +}; + +/* bit allocation table */ +static +struct { + unsigned short nbal; + unsigned short offset; +} const bitalloc_table[8] = { + { 2, 0 }, /* 0 */ + { 2, 3 }, /* 1 */ + { 3, 3 }, /* 2 */ + { 3, 1 }, /* 3 */ + { 4, 2 }, /* 4 */ + { 4, 3 }, /* 5 */ + { 4, 4 }, /* 6 */ + { 4, 5 } /* 7 */ +}; + +/* offsets into quantization class table */ +static +unsigned char const offset_table[6][15] = { + { 0, 1, 16 }, /* 0 */ + { 0, 1, 2, 3, 4, 5, 16 }, /* 1 */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, /* 2 */ + { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, /* 3 */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16 }, /* 4 */ + { 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 } /* 5 */ +}; + +/* quantization class table */ +static +struct quantclass { + unsigned short nlevels; + unsigned char group; + unsigned char bits; + mad_fixed_t C; + mad_fixed_t D; +} const qc_table[17] = { +# include "qc_table.dat" +}; + +/* + * NAME: II_samples() + * DESCRIPTION: decode three requantized Layer II samples from a bitstream + */ +static +void II_samples(struct mad_bitptr *ptr, + struct quantclass const *quantclass, + mad_fixed_t output[3]) +{ + unsigned int nb, s, sample[3]; + + if ((nb = quantclass->group)) { + unsigned int c, nlevels; + + /* degrouping */ + c = mad_bit_read(ptr, quantclass->bits); + nlevels = quantclass->nlevels; + + for (s = 0; s < 3; ++s) { + sample[s] = c % nlevels; + c /= nlevels; + } + } + else { + nb = quantclass->bits; + + for (s = 0; s < 3; ++s) + sample[s] = mad_bit_read(ptr, nb); + } + + for (s = 0; s < 3; ++s) { + mad_fixed_t requantized; + + /* invert most significant bit, extend sign, then scale to fixed format */ + + requantized = sample[s] ^ (1 << (nb - 1)); + requantized |= -(requantized & (1 << (nb - 1))); + + requantized <<= MAD_F_FRACBITS - (nb - 1); + + /* requantize the sample */ + + /* s'' = C * (s''' + D) */ + + output[s] = mad_f_mul(requantized + quantclass->D, quantclass->C); + + /* s' = factor * s'' */ + /* (to be performed by caller) */ + } +} + +/* + * NAME: layer->II() + * DESCRIPTION: decode a single Layer II frame + */ +int mad_layer_II(struct mad_stream *stream, struct mad_frame *frame) +{ + struct mad_header *header = &frame->header; + struct mad_bitptr start; + unsigned int index, sblimit, nbal, nch, bound, gr, ch, s, sb; + unsigned char const *offsets; + unsigned char allocation[2][32], scfsi[2][32], scalefactor[2][32][3]; + mad_fixed_t samples[3]; + + nch = MAD_NCHANNELS(header); + + if (header->flags & MAD_FLAG_LSF_EXT) + index = 4; + else { + switch (nch == 2 ? header->bitrate / 2 : header->bitrate) { + case 32000: + case 48000: + index = (header->samplerate == 32000) ? 3 : 2; + break; + + case 56000: + case 64000: + case 80000: + index = 0; + break; + + default: + index = (header->samplerate == 48000) ? 0 : 1; + } + } + + sblimit = sbquant_table[index].sblimit; + offsets = sbquant_table[index].offsets; + + bound = 32; + if (header->mode == MAD_MODE_JOINT_STEREO) { + header->flags |= MAD_FLAG_I_STEREO; + bound = 4 + header->mode_extension * 4; + } + + if (bound > sblimit) + bound = sblimit; + + start = stream->ptr; + + /* decode bit allocations */ + + for (sb = 0; sb < bound; ++sb) { + nbal = bitalloc_table[offsets[sb]].nbal; + + for (ch = 0; ch < nch; ++ch) + allocation[ch][sb] = mad_bit_read(&stream->ptr, nbal); + } + + for (sb = bound; sb < sblimit; ++sb) { + nbal = bitalloc_table[offsets[sb]].nbal; + + allocation[0][sb] = + allocation[1][sb] = mad_bit_read(&stream->ptr, nbal); + } + + /* decode scalefactor selection info */ + + for (sb = 0; sb < sblimit; ++sb) { + for (ch = 0; ch < nch; ++ch) { + if (allocation[ch][sb]) + scfsi[ch][sb] = mad_bit_read(&stream->ptr, 2); + } + } + + /* check CRC word */ + + if (header->flags & MAD_FLAG_PROTECTION) { + header->crc_check = + mad_bit_crc(start, mad_bit_length(&start, &stream->ptr), + header->crc_check); + + if (header->crc_check != header->crc_target && + !(frame->options & MAD_OPTION_IGNORECRC)) { + stream->error = MAD_ERROR_BADCRC; + return -1; + } + } + + /* decode scalefactors */ + + for (sb = 0; sb < sblimit; ++sb) { + for (ch = 0; ch < nch; ++ch) { + if (allocation[ch][sb]) { + scalefactor[ch][sb][0] = mad_bit_read(&stream->ptr, 6); + + switch (scfsi[ch][sb]) { + case 2: + scalefactor[ch][sb][2] = + scalefactor[ch][sb][1] = + scalefactor[ch][sb][0]; + break; + + case 0: + scalefactor[ch][sb][1] = mad_bit_read(&stream->ptr, 6); + /* fall through */ + + case 1: + case 3: + scalefactor[ch][sb][2] = mad_bit_read(&stream->ptr, 6); + } + + if (scfsi[ch][sb] & 1) + scalefactor[ch][sb][1] = scalefactor[ch][sb][scfsi[ch][sb] - 1]; + + if (scalefactor[ch][sb][0] == 63 || + scalefactor[ch][sb][1] == 63 || + scalefactor[ch][sb][2] == 63) { + stream->error = MAD_ERROR_BADSCALEFACTOR; + return -1; + } + } + } + } + + /* decode samples */ + + for (gr = 0; gr < 12; ++gr) { + for (sb = 0; sb < bound; ++sb) { + for (ch = 0; ch < nch; ++ch) { + if ((index = allocation[ch][sb])) { + index = offset_table[bitalloc_table[offsets[sb]].offset][index - 1]; + + II_samples(&stream->ptr, &qc_table[index], samples); + + for (s = 0; s < 3; ++s) { + frame->sbsample[ch][3 * gr + s][sb] = + mad_f_mul(samples[s], sf_table[scalefactor[ch][sb][gr / 4]]); + } + } + else { + for (s = 0; s < 3; ++s) + frame->sbsample[ch][3 * gr + s][sb] = 0; + } + } + } + + for (sb = bound; sb < sblimit; ++sb) { + if ((index = allocation[0][sb])) { + index = offset_table[bitalloc_table[offsets[sb]].offset][index - 1]; + + II_samples(&stream->ptr, &qc_table[index], samples); + + for (ch = 0; ch < nch; ++ch) { + for (s = 0; s < 3; ++s) { + frame->sbsample[ch][3 * gr + s][sb] = + mad_f_mul(samples[s], sf_table[scalefactor[ch][sb][gr / 4]]); + } + } + } + else { + for (ch = 0; ch < nch; ++ch) { + for (s = 0; s < 3; ++s) + frame->sbsample[ch][3 * gr + s][sb] = 0; + } + } + } + + for (ch = 0; ch < nch; ++ch) { + for (s = 0; s < 3; ++s) { + for (sb = sblimit; sb < 32; ++sb) + frame->sbsample[ch][3 * gr + s][sb] = 0; + } + } + } + + return 0; +} diff --git a/core/multimedia/opieplayer/libmad/layer12.h b/core/multimedia/opieplayer/libmad/layer12.h new file mode 100644 index 0000000..d2c81ac --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/layer12.h @@ -0,0 +1,31 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_LAYER12_H +# define LIBMAD_LAYER12_H + +# include "stream.h" +# include "frame.h" + +int mad_layer_I(struct mad_stream *, struct mad_frame *); +int mad_layer_II(struct mad_stream *, struct mad_frame *); + +# endif diff --git a/core/multimedia/opieplayer/libmad/layer3.c b/core/multimedia/opieplayer/libmad/layer3.c new file mode 100644 index 0000000..194fc7e --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/layer3.c @@ -0,0 +1,2492 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifdef HAVE_CONFIG_H +# include "libmad_config.h" +# endif + +# include "libmad_global.h" + +# include +# include +# include + +# ifdef HAVE_LIMITS_H +# include +# else +# define CHAR_BIT 8 +# endif + +# include "fixed.h" +# include "bit.h" +# include "stream.h" +# include "frame.h" +# include "huffman.h" +# include "layer3.h" + +/* --- Layer III ----------------------------------------------------------- */ + +enum { + count1table_select = 0x01, + scalefac_scale = 0x02, + preflag = 0x04, + mixed_block_flag = 0x08 +}; + +struct sideinfo { + unsigned int main_data_begin; + unsigned int private_bits; + + unsigned char scfsi[2]; + + struct granule { + struct channel { + /* from side info */ + unsigned short part2_3_length; + unsigned short big_values; + unsigned short global_gain; + unsigned short scalefac_compress; + + unsigned char flags; + unsigned char block_type; + unsigned char table_select[3]; + unsigned char subblock_gain[3]; + unsigned char region0_count; + unsigned char region1_count; + + /* from main_data */ + unsigned char scalefac[39]; /* scalefac_l and/or scalefac_s */ + } ch[2]; + } gr[2]; +}; + +/* + * scalefactor bit lengths + * derived from section 2.4.2.7 of ISO/IEC 11172-3 + */ +static +struct { + unsigned char slen1; + unsigned char slen2; +} const sflen_table[16] = { + { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, + { 3, 0 }, { 1, 1 }, { 1, 2 }, { 1, 3 }, + { 2, 1 }, { 2, 2 }, { 2, 3 }, { 3, 1 }, + { 3, 2 }, { 3, 3 }, { 4, 2 }, { 4, 3 } +}; + +/* + * number of LSF scalefactor band values + * derived from section 2.4.3.2 of ISO/IEC 13818-3 + */ +static +unsigned char const nsfb_table[6][3][4] = { + { { 6, 5, 5, 5 }, + { 9, 9, 9, 9 }, + { 6, 9, 9, 9 } }, + + { { 6, 5, 7, 3 }, + { 9, 9, 12, 6 }, + { 6, 9, 12, 6 } }, + + { { 11, 10, 0, 0 }, + { 18, 18, 0, 0 }, + { 15, 18, 0, 0 } }, + + { { 7, 7, 7, 0 }, + { 12, 12, 12, 0 }, + { 6, 15, 12, 0 } }, + + { { 6, 6, 6, 3 }, + { 12, 9, 9, 6 }, + { 6, 12, 9, 6 } }, + + { { 8, 8, 5, 0 }, + { 15, 12, 9, 0 }, + { 6, 18, 9, 0 } } +}; + +/* + * MPEG-1 scalefactor band widths + * derived from Table B.8 of ISO/IEC 11172-3 + */ +static +unsigned char const sfb_48000_long[] = { + 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 10, + 12, 16, 18, 22, 28, 34, 40, 46, 54, 54, 192 +}; + +static +unsigned char const sfb_44100_long[] = { + 4, 4, 4, 4, 4, 4, 6, 6, 8, 8, 10, + 12, 16, 20, 24, 28, 34, 42, 50, 54, 76, 158 +}; + +static +unsigned char const sfb_32000_long[] = { + 4, 4, 4, 4, 4, 4, 6, 6, 8, 10, 12, + 16, 20, 24, 30, 38, 46, 56, 68, 84, 102, 26 +}; + +static +unsigned char const sfb_48000_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, + 6, 6, 6, 6, 6, 10, 10, 10, 12, 12, 12, 14, 14, + 14, 16, 16, 16, 20, 20, 20, 26, 26, 26, 66, 66, 66 +}; + +static +unsigned char const sfb_44100_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, + 6, 6, 8, 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, + 14, 18, 18, 18, 22, 22, 22, 30, 30, 30, 56, 56, 56 +}; + +static +unsigned char const sfb_32000_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, + 6, 6, 8, 8, 8, 12, 12, 12, 16, 16, 16, 20, 20, + 20, 26, 26, 26, 34, 34, 34, 42, 42, 42, 12, 12, 12 +}; + +static +unsigned char const sfb_48000_mixed[] = { + /* long */ 4, 4, 4, 4, 4, 4, 6, 6, + /* short */ 4, 4, 4, 6, 6, 6, 6, 6, 6, 10, + 10, 10, 12, 12, 12, 14, 14, 14, 16, 16, + 16, 20, 20, 20, 26, 26, 26, 66, 66, 66 +}; + +static +unsigned char const sfb_44100_mixed[] = { + /* long */ 4, 4, 4, 4, 4, 4, 6, 6, + /* short */ 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, + 10, 10, 12, 12, 12, 14, 14, 14, 18, 18, + 18, 22, 22, 22, 30, 30, 30, 56, 56, 56 +}; + +static +unsigned char const sfb_32000_mixed[] = { + /* long */ 4, 4, 4, 4, 4, 4, 6, 6, + /* short */ 4, 4, 4, 6, 6, 6, 8, 8, 8, 12, + 12, 12, 16, 16, 16, 20, 20, 20, 26, 26, + 26, 34, 34, 34, 42, 42, 42, 12, 12, 12 +}; + +/* + * MPEG-2 scalefactor band widths + * derived from Table B.2 of ISO/IEC 13818-3 + */ +static +unsigned char const sfb_24000_long[] = { + 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 18, 22, 26, 32, 38, 46, 54, 62, 70, 76, 36 +}; + +static +unsigned char const sfb_22050_long[] = { + 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54 +}; + +# define sfb_16000_long sfb_22050_long + +static +unsigned char const sfb_24000_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, + 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, 14, 18, 18, + 18, 24, 24, 24, 32, 32, 32, 44, 44, 44, 12, 12, 12 +}; + +static +unsigned char const sfb_22050_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, + 6, 6, 8, 8, 8, 10, 10, 10, 14, 14, 14, 18, 18, + 18, 26, 26, 26, 32, 32, 32, 42, 42, 42, 18, 18, 18 +}; + +static +unsigned char const sfb_16000_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, + 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, 14, 18, 18, + 18, 24, 24, 24, 30, 30, 30, 40, 40, 40, 18, 18, 18 +}; + +static +unsigned char const sfb_24000_mixed[] = { + /* long */ 6, 6, 6, 6, 6, 6, + /* short */ 6, 6, 6, 8, 8, 8, 10, 10, 10, 12, + 12, 12, 14, 14, 14, 18, 18, 18, 24, 24, + 24, 32, 32, 32, 44, 44, 44, 12, 12, 12 +}; + +static +unsigned char const sfb_22050_mixed[] = { + /* long */ 6, 6, 6, 6, 6, 6, + /* short */ 6, 6, 6, 6, 6, 6, 8, 8, 8, 10, + 10, 10, 14, 14, 14, 18, 18, 18, 26, 26, + 26, 32, 32, 32, 42, 42, 42, 18, 18, 18 +}; + +static +unsigned char const sfb_16000_mixed[] = { + /* long */ 6, 6, 6, 6, 6, 6, + /* short */ 6, 6, 6, 8, 8, 8, 10, 10, 10, 12, + 12, 12, 14, 14, 14, 18, 18, 18, 24, 24, + 24, 30, 30, 30, 40, 40, 40, 18, 18, 18 +}; + +/* + * MPEG 2.5 scalefactor band widths + * derived from public sources + */ +# define sfb_12000_long sfb_16000_long +# define sfb_11025_long sfb_12000_long + +static +unsigned char const sfb_8000_long[] = { + 12, 12, 12, 12, 12, 12, 16, 20, 24, 28, 32, + 40, 48, 56, 64, 76, 90, 2, 2, 2, 2, 2 +}; + +# define sfb_12000_short sfb_16000_short +# define sfb_11025_short sfb_12000_short + +static +unsigned char const sfb_8000_short[] = { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 16, + 16, 16, 20, 20, 20, 24, 24, 24, 28, 28, 28, 36, 36, + 36, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 26, 26 +}; + +# define sfb_12000_mixed sfb_16000_mixed +# define sfb_11025_mixed sfb_12000_mixed + +/* the 8000 Hz short block scalefactor bands do not break after the first 36 + frequency lines, so this is probably wrong */ +static +unsigned char const sfb_8000_mixed[] = { + /* long */ 12, 12, 12, + /* short */ 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16, + 20, 20, 20, 24, 24, 24, 28, 28, 28, 36, 36, 36, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 26, 26 +}; + +static +struct { + unsigned char const *l; + unsigned char const *s; + unsigned char const *m; +} const sfbwidth_table[9] = { + { sfb_48000_long, sfb_48000_short, sfb_48000_mixed }, + { sfb_44100_long, sfb_44100_short, sfb_44100_mixed }, + { sfb_32000_long, sfb_32000_short, sfb_32000_mixed }, + { sfb_24000_long, sfb_24000_short, sfb_24000_mixed }, + { sfb_22050_long, sfb_22050_short, sfb_22050_mixed }, + { sfb_16000_long, sfb_16000_short, sfb_16000_mixed }, + { sfb_12000_long, sfb_12000_short, sfb_12000_mixed }, + { sfb_11025_long, sfb_11025_short, sfb_11025_mixed }, + { sfb_8000_long, sfb_8000_short, sfb_8000_mixed } +}; + +/* + * scalefactor band preemphasis (used only when preflag is set) + * derived from Table B.6 of ISO/IEC 11172-3 + */ +static +unsigned char const pretab[22] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 +}; + +/* + * table for requantization + * + * rq_table[x].mantissa * 2^(rq_table[x].exponent) = x^(4/3) + */ +static +struct fixedfloat { + unsigned long mantissa : 27; + unsigned short exponent : 5; +} const rq_table[8207] = { +# include "rq_table.dat" +}; + +/* + * fractional powers of two + * used for requantization and joint stereo decoding + * + * root_table[3 + x] = 2^(x/4) + */ +static +mad_fixed_t const root_table[7] = { + MAD_F(0x09837f05) /* 2^(-3/4) == 0.59460355750136 */, + MAD_F(0x0b504f33) /* 2^(-2/4) == 0.70710678118655 */, + MAD_F(0x0d744fcd) /* 2^(-1/4) == 0.84089641525371 */, + MAD_F(0x10000000) /* 2^( 0/4) == 1.00000000000000 */, + MAD_F(0x1306fe0a) /* 2^(+1/4) == 1.18920711500272 */, + MAD_F(0x16a09e66) /* 2^(+2/4) == 1.41421356237310 */, + MAD_F(0x1ae89f99) /* 2^(+3/4) == 1.68179283050743 */ +}; + +/* + * coefficients for aliasing reduction + * derived from Table B.9 of ISO/IEC 11172-3 + * + * c[] = { -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037 } + * cs[i] = 1 / sqrt(1 + c[i]^2) + * ca[i] = c[i] / sqrt(1 + c[i]^2) + */ +static +mad_fixed_t const cs[8] = { + +MAD_F(0x0db84a81) /* +0.857492926 */, +MAD_F(0x0e1b9d7f) /* +0.881741997 */, + +MAD_F(0x0f31adcf) /* +0.949628649 */, +MAD_F(0x0fbba815) /* +0.983314592 */, + +MAD_F(0x0feda417) /* +0.995517816 */, +MAD_F(0x0ffc8fc8) /* +0.999160558 */, + +MAD_F(0x0fff964c) /* +0.999899195 */, +MAD_F(0x0ffff8d3) /* +0.999993155 */ +}; + +static +mad_fixed_t const ca[8] = { + -MAD_F(0x083b5fe7) /* -0.514495755 */, -MAD_F(0x078c36d2) /* -0.471731969 */, + -MAD_F(0x05039814) /* -0.313377454 */, -MAD_F(0x02e91dd1) /* -0.181913200 */, + -MAD_F(0x0183603a) /* -0.094574193 */, -MAD_F(0x00a7cb87) /* -0.040965583 */, + -MAD_F(0x003a2847) /* -0.014198569 */, -MAD_F(0x000f27b4) /* -0.003699975 */ +}; + +/* + * IMDCT coefficients for short blocks + * derived from section 2.4.3.4.10.2 of ISO/IEC 11172-3 + * + * imdct_s[i/even][k] = cos((PI / 24) * (2 * (i / 2) + 7) * (2 * k + 1)) + * imdct_s[i /odd][k] = cos((PI / 24) * (2 * (6 + (i-1)/2) + 7) * (2 * k + 1)) + */ +static +mad_fixed_t const imdct_s[6][6] = { +# include "imdct_s.dat" +}; + +# if !defined(ASO_IMDCT) +/* + * windowing coefficients for long blocks + * derived from section 2.4.3.4.10.3 of ISO/IEC 11172-3 + * + * window_l[i] = sin((PI / 36) * (i + 1/2)) + */ +static +mad_fixed_t const window_l[36] = { + MAD_F(0x00b2aa3e) /* 0.043619387 */, MAD_F(0x0216a2a2) /* 0.130526192 */, + MAD_F(0x03768962) /* 0.216439614 */, MAD_F(0x04cfb0e2) /* 0.300705800 */, + MAD_F(0x061f78aa) /* 0.382683432 */, MAD_F(0x07635284) /* 0.461748613 */, + MAD_F(0x0898c779) /* 0.537299608 */, MAD_F(0x09bd7ca0) /* 0.608761429 */, + MAD_F(0x0acf37ad) /* 0.675590208 */, MAD_F(0x0bcbe352) /* 0.737277337 */, + MAD_F(0x0cb19346) /* 0.793353340 */, MAD_F(0x0d7e8807) /* 0.843391446 */, + + MAD_F(0x0e313245) /* 0.887010833 */, MAD_F(0x0ec835e8) /* 0.923879533 */, + MAD_F(0x0f426cb5) /* 0.953716951 */, MAD_F(0x0f9ee890) /* 0.976296007 */, + MAD_F(0x0fdcf549) /* 0.991444861 */, MAD_F(0x0ffc19fd) /* 0.999048222 */, + MAD_F(0x0ffc19fd) /* 0.999048222 */, MAD_F(0x0fdcf549) /* 0.991444861 */, + MAD_F(0x0f9ee890) /* 0.976296007 */, MAD_F(0x0f426cb5) /* 0.953716951 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, MAD_F(0x0e313245) /* 0.887010833 */, + + MAD_F(0x0d7e8807) /* 0.843391446 */, MAD_F(0x0cb19346) /* 0.793353340 */, + MAD_F(0x0bcbe352) /* 0.737277337 */, MAD_F(0x0acf37ad) /* 0.675590208 */, + MAD_F(0x09bd7ca0) /* 0.608761429 */, MAD_F(0x0898c779) /* 0.537299608 */, + MAD_F(0x07635284) /* 0.461748613 */, MAD_F(0x061f78aa) /* 0.382683432 */, + MAD_F(0x04cfb0e2) /* 0.300705800 */, MAD_F(0x03768962) /* 0.216439614 */, + MAD_F(0x0216a2a2) /* 0.130526192 */, MAD_F(0x00b2aa3e) /* 0.043619387 */, +}; +# endif /* ASO_IMDCT */ + +/* + * windowing coefficients for short blocks + * derived from section 2.4.3.4.10.3 of ISO/IEC 11172-3 + * + * window_s[i] = sin((PI / 12) * (i + 1/2)) + */ +static +mad_fixed_t const window_s[12] = { + MAD_F(0x0216a2a2) /* 0.130526192 */, MAD_F(0x061f78aa) /* 0.382683432 */, + MAD_F(0x09bd7ca0) /* 0.608761429 */, MAD_F(0x0cb19346) /* 0.793353340 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, MAD_F(0x0fdcf549) /* 0.991444861 */, + MAD_F(0x0fdcf549) /* 0.991444861 */, MAD_F(0x0ec835e8) /* 0.923879533 */, + MAD_F(0x0cb19346) /* 0.793353340 */, MAD_F(0x09bd7ca0) /* 0.608761429 */, + MAD_F(0x061f78aa) /* 0.382683432 */, MAD_F(0x0216a2a2) /* 0.130526192 */, +}; + +/* + * coefficients for intensity stereo processing + * derived from section 2.4.3.4.9.3 of ISO/IEC 11172-3 + * + * is_ratio[i] = tan(i * (PI / 12)) + * is_table[i] = is_ratio[i] / (1 + is_ratio[i]) + */ +static +mad_fixed_t const is_table[7] = { + MAD_F(0x00000000) /* 0.000000000 */, + MAD_F(0x0361962f) /* 0.211324865 */, + MAD_F(0x05db3d74) /* 0.366025404 */, + MAD_F(0x08000000) /* 0.500000000 */, + MAD_F(0x0a24c28c) /* 0.633974596 */, + MAD_F(0x0c9e69d1) /* 0.788675135 */, + MAD_F(0x10000000) /* 1.000000000 */ +}; + +/* + * coefficients for LSF intensity stereo processing + * derived from section 2.4.3.2 of ISO/IEC 13818-3 + * + * is_lsf_table[0][i] = (1 / sqrt(sqrt(2)))^(i + 1) + * is_lsf_table[1][i] = (1 / sqrt(2))^(i + 1) + */ +static +mad_fixed_t const is_lsf_table[2][15] = { + { + MAD_F(0x0d744fcd) /* 0.840896415 */, + MAD_F(0x0b504f33) /* 0.707106781 */, + MAD_F(0x09837f05) /* 0.594603558 */, + MAD_F(0x08000000) /* 0.500000000 */, + MAD_F(0x06ba27e6) /* 0.420448208 */, + MAD_F(0x05a8279a) /* 0.353553391 */, + MAD_F(0x04c1bf83) /* 0.297301779 */, + MAD_F(0x04000000) /* 0.250000000 */, + MAD_F(0x035d13f3) /* 0.210224104 */, + MAD_F(0x02d413cd) /* 0.176776695 */, + MAD_F(0x0260dfc1) /* 0.148650889 */, + MAD_F(0x02000000) /* 0.125000000 */, + MAD_F(0x01ae89fa) /* 0.105112052 */, + MAD_F(0x016a09e6) /* 0.088388348 */, + MAD_F(0x01306fe1) /* 0.074325445 */ + }, { + MAD_F(0x0b504f33) /* 0.707106781 */, + MAD_F(0x08000000) /* 0.500000000 */, + MAD_F(0x05a8279a) /* 0.353553391 */, + MAD_F(0x04000000) /* 0.250000000 */, + MAD_F(0x02d413cd) /* 0.176776695 */, + MAD_F(0x02000000) /* 0.125000000 */, + MAD_F(0x016a09e6) /* 0.088388348 */, + MAD_F(0x01000000) /* 0.062500000 */, + MAD_F(0x00b504f3) /* 0.044194174 */, + MAD_F(0x00800000) /* 0.031250000 */, + MAD_F(0x005a827a) /* 0.022097087 */, + MAD_F(0x00400000) /* 0.015625000 */, + MAD_F(0x002d413d) /* 0.011048543 */, + MAD_F(0x00200000) /* 0.007812500 */, + MAD_F(0x0016a09e) /* 0.005524272 */ + } +}; + +/* + * NAME: III_sideinfo() + * DESCRIPTION: decode frame side information from a bitstream + */ +static +enum mad_error III_sideinfo(struct mad_bitptr *ptr, unsigned int nch, + int lsf, struct sideinfo *si, + unsigned int *data_bitlen, + unsigned int *priv_bitlen) +{ + unsigned int ngr, gr, ch, i; + enum mad_error result = 0; + + *data_bitlen = 0; + *priv_bitlen = lsf ? ((nch == 1) ? 1 : 2) : ((nch == 1) ? 5 : 3); + + si->main_data_begin = mad_bit_read(ptr, lsf ? 8 : 9); + si->private_bits = mad_bit_read(ptr, *priv_bitlen); + + ngr = 1; + if (!lsf) { + ngr = 2; + + for (ch = 0; ch < nch; ++ch) + si->scfsi[ch] = mad_bit_read(ptr, 4); + } + + for (gr = 0; gr < ngr; ++gr) { + struct granule *granule = &si->gr[gr]; + + for (ch = 0; ch < nch; ++ch) { + struct channel *channel = &granule->ch[ch]; + + channel->part2_3_length = mad_bit_read(ptr, 12); + channel->big_values = mad_bit_read(ptr, 9); + channel->global_gain = mad_bit_read(ptr, 8); + channel->scalefac_compress = mad_bit_read(ptr, lsf ? 9 : 4); + + *data_bitlen += channel->part2_3_length; + + if (channel->big_values > 288 && result == 0) + result = MAD_ERROR_BADBIGVALUES; + + channel->flags = 0; + + /* window_switching_flag */ + if (mad_bit_read(ptr, 1)) { + channel->block_type = mad_bit_read(ptr, 2); + + if (channel->block_type == 0 && result == 0) + result = MAD_ERROR_BADBLOCKTYPE; + + if (!lsf && channel->block_type == 2 && si->scfsi[ch] && result == 0) + result = MAD_ERROR_BADSCFSI; + + channel->region0_count = 7; + channel->region1_count = 36; + + if (mad_bit_read(ptr, 1)) + channel->flags |= mixed_block_flag; + else if (channel->block_type == 2) + channel->region0_count = 8; + + for (i = 0; i < 2; ++i) + channel->table_select[i] = mad_bit_read(ptr, 5); + +# if defined(DEBUG) + channel->table_select[2] = 4; /* not used */ +# endif + + for (i = 0; i < 3; ++i) + channel->subblock_gain[i] = mad_bit_read(ptr, 3); + } + else { + channel->block_type = 0; + + for (i = 0; i < 3; ++i) + channel->table_select[i] = mad_bit_read(ptr, 5); + + channel->region0_count = mad_bit_read(ptr, 4); + channel->region1_count = mad_bit_read(ptr, 3); + } + + /* [preflag,] scalefac_scale, count1table_select */ + channel->flags |= mad_bit_read(ptr, lsf ? 2 : 3); + } + } + + return result; +} + +/* + * NAME: III_scalefactors_lsf() + * DESCRIPTION: decode channel scalefactors for LSF from a bitstream + */ +static +unsigned int III_scalefactors_lsf(struct mad_bitptr *ptr, + struct channel *channel, + struct channel *gr1ch, int mode_extension) +{ + struct mad_bitptr start; + unsigned int scalefac_compress, index, slen[4], part, n, i; + unsigned char const *nsfb; + + start = *ptr; + + scalefac_compress = channel->scalefac_compress; + index = (channel->block_type == 2) ? + ((channel->flags & mixed_block_flag) ? 2 : 1) : 0; + + if (!((mode_extension & 0x1) && gr1ch)) { + if (scalefac_compress < 400) { + slen[0] = (scalefac_compress >> 4) / 5; + slen[1] = (scalefac_compress >> 4) % 5; + slen[2] = (scalefac_compress % 16) >> 2; + slen[3] = scalefac_compress % 4; + + nsfb = nsfb_table[0][index]; + } + else if (scalefac_compress < 500) { + scalefac_compress -= 400; + + slen[0] = (scalefac_compress >> 2) / 5; + slen[1] = (scalefac_compress >> 2) % 5; + slen[2] = scalefac_compress % 4; + slen[3] = 0; + + nsfb = nsfb_table[1][index]; + } + else { + scalefac_compress -= 500; + + slen[0] = scalefac_compress / 3; + slen[1] = scalefac_compress % 3; + slen[2] = 0; + slen[3] = 0; + + channel->flags |= preflag; + + nsfb = nsfb_table[2][index]; + } + + n = 0; + for (part = 0; part < 4; ++part) { + for (i = 0; i < nsfb[part]; ++i) + channel->scalefac[n++] = mad_bit_read(ptr, slen[part]); + } + + while (n < 39) + channel->scalefac[n++] = 0; + } + else { /* (mode_extension & 0x1) && gr1ch (i.e. ch == 1) */ + scalefac_compress >>= 1; + + if (scalefac_compress < 180) { + slen[0] = scalefac_compress / 36; + slen[1] = (scalefac_compress % 36) / 6; + slen[2] = (scalefac_compress % 36) % 6; + slen[3] = 0; + + nsfb = nsfb_table[3][index]; + } + else if (scalefac_compress < 244) { + scalefac_compress -= 180; + + slen[0] = (scalefac_compress % 64) >> 4; + slen[1] = (scalefac_compress % 16) >> 2; + slen[2] = scalefac_compress % 4; + slen[3] = 0; + + nsfb = nsfb_table[4][index]; + } + else { + scalefac_compress -= 244; + + slen[0] = scalefac_compress / 3; + slen[1] = scalefac_compress % 3; + slen[2] = 0; + slen[3] = 0; + + nsfb = nsfb_table[5][index]; + } + + n = 0; + for (part = 0; part < 4; ++part) { + unsigned int max, is_pos; + + max = (1 << slen[part]) - 1; + + for (i = 0; i < nsfb[part]; ++i) { + is_pos = mad_bit_read(ptr, slen[part]); + + channel->scalefac[n] = is_pos; + gr1ch->scalefac[n++] = (is_pos == max); + } + } + + while (n < 39) { + channel->scalefac[n] = 0; + gr1ch->scalefac[n++] = 0; /* apparently not illegal */ + } + } + + return mad_bit_length(&start, ptr); +} + +/* + * NAME: III_scalefactors() + * DESCRIPTION: decode channel scalefactors of one granule from a bitstream + */ +static +unsigned int III_scalefactors(struct mad_bitptr *ptr, struct channel *channel, + struct channel const *gr0ch, unsigned int scfsi) +{ + struct mad_bitptr start; + unsigned int slen1, slen2, sfbi; + + start = *ptr; + + slen1 = sflen_table[channel->scalefac_compress].slen1; + slen2 = sflen_table[channel->scalefac_compress].slen2; + + if (channel->block_type == 2) { + unsigned int nsfb; + + sfbi = 0; + + nsfb = (channel->flags & mixed_block_flag) ? 8 + 3 * 3 : 6 * 3; + while (nsfb--) + channel->scalefac[sfbi++] = mad_bit_read(ptr, slen1); + + nsfb = 6 * 3; + while (nsfb--) + channel->scalefac[sfbi++] = mad_bit_read(ptr, slen2); + + nsfb = 1 * 3; + while (nsfb--) + channel->scalefac[sfbi++] = 0; + } + else { /* channel->block_type != 2 */ + if (scfsi & 0x8) { + for (sfbi = 0; sfbi < 6; ++sfbi) + channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; + } + else { + for (sfbi = 0; sfbi < 6; ++sfbi) + channel->scalefac[sfbi] = mad_bit_read(ptr, slen1); + } + + if (scfsi & 0x4) { + for (sfbi = 6; sfbi < 11; ++sfbi) + channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; + } + else { + for (sfbi = 6; sfbi < 11; ++sfbi) + channel->scalefac[sfbi] = mad_bit_read(ptr, slen1); + } + + if (scfsi & 0x2) { + for (sfbi = 11; sfbi < 16; ++sfbi) + channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; + } + else { + for (sfbi = 11; sfbi < 16; ++sfbi) + channel->scalefac[sfbi] = mad_bit_read(ptr, slen2); + } + + if (scfsi & 0x1) { + for (sfbi = 16; sfbi < 21; ++sfbi) + channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; + } + else { + for (sfbi = 16; sfbi < 21; ++sfbi) + channel->scalefac[sfbi] = mad_bit_read(ptr, slen2); + } + + channel->scalefac[21] = 0; + } + + return mad_bit_length(&start, ptr); +} + +/* + * NAME: III_exponents() + * DESCRIPTION: calculate scalefactor exponents + */ +static +void III_exponents(struct channel const *channel, + unsigned char const *sfbwidth, signed int exponents[39]) +{ + signed int gain; + unsigned int scalefac_multiplier, sfbi; + + gain = (signed int) channel->global_gain - 210; + scalefac_multiplier = (channel->flags & scalefac_scale) ? 2 : 1; + + if (channel->block_type == 2) { + unsigned int l; + signed int gain0, gain1, gain2; + + sfbi = l = 0; + + if (channel->flags & mixed_block_flag) { + unsigned int premask; + + premask = (channel->flags & preflag) ? ~0 : 0; + + /* long block subbands 0-1 */ + + while (l < 36) { + exponents[sfbi] = gain - + (signed int) ((channel->scalefac[sfbi] + (pretab[sfbi] & premask)) << + scalefac_multiplier); + + l += sfbwidth[sfbi++]; + } + } + + /* this is probably wrong for 8000 Hz short/mixed blocks */ + + gain0 = gain - 8 * (signed int) channel->subblock_gain[0]; + gain1 = gain - 8 * (signed int) channel->subblock_gain[1]; + gain2 = gain - 8 * (signed int) channel->subblock_gain[2]; + + while (l < 576) { + exponents[sfbi + 0] = gain0 - + (signed int) (channel->scalefac[sfbi + 0] << scalefac_multiplier); + exponents[sfbi + 1] = gain1 - + (signed int) (channel->scalefac[sfbi + 1] << scalefac_multiplier); + exponents[sfbi + 2] = gain2 - + (signed int) (channel->scalefac[sfbi + 2] << scalefac_multiplier); + + l += 3 * sfbwidth[sfbi]; + sfbi += 3; + } + } + else { /* channel->block_type != 2 */ + if (channel->flags & preflag) { + for (sfbi = 0; sfbi < 22; ++sfbi) { + exponents[sfbi] = gain - + (signed int) ((channel->scalefac[sfbi] + pretab[sfbi]) << + scalefac_multiplier); + } + } + else { + for (sfbi = 0; sfbi < 22; ++sfbi) { + exponents[sfbi] = gain - + (signed int) (channel->scalefac[sfbi] << scalefac_multiplier); + } + } + } +} + +/* + * NAME: III_requantize() + * DESCRIPTION: requantize one (positive) value + */ +static +mad_fixed_t III_requantize(unsigned int value, signed int exp) +{ + mad_fixed_t requantized; + signed int frac; + struct fixedfloat const *power; + + /* + * long blocks: + * xr[i] = sign(is[i]) * abs(is[i])^(4/3) * + * 2^((1/4) * (global_gain - 210)) * + * 2^-(scalefac_multiplier * + * (scalefac_l[sfb] + preflag * pretab[sfb])) + * + * short blocks: + * xr[i] = sign(is[i]) * abs(is[i])^(4/3) * + * 2^((1/4) * (global_gain - 210 - 8 * subblock_gain[w])) * + * 2^-(scalefac_multiplier * scalefac_s[sfb][w]) + * + * where: + * scalefac_multiplier = (scalefac_scale + 1) / 2 + */ + + frac = exp % 4; + exp /= 4; + + power = &rq_table[value]; + requantized = power->mantissa; + exp += power->exponent; + + if (exp < 0) { + if (-exp >= sizeof(mad_fixed_t) * CHAR_BIT) { + /* underflow */ + requantized = 0; + } + else + requantized >>= -exp; + } + else { + if (exp >= 5) { + /* overflow */ +# if defined(DEBUG) + fprintf(stderr, "requantize overflow (%f * 2^%d)\n", + mad_f_todouble(requantized), exp); +# endif + requantized = MAD_F_MAX; + } + else + requantized <<= exp; + } + + return frac ? mad_f_mul(requantized, root_table[3 + frac]) : requantized; +} + +/* we must take care that sz >= bits and sz < sizeof(long) lest bits == 0 */ +# define MASK(cache, sz, bits) \ + (((cache) >> ((sz) - (bits))) & ((1 << (bits)) - 1)) +# define MASK1BIT(cache, sz) \ + ((cache) & (1 << ((sz) - 1))) + +/* + * NAME: III_huffdecode() + * DESCRIPTION: decode Huffman code words of one channel of one granule + */ +static +enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], + struct channel *channel, + unsigned char const *sfbwidth, + unsigned int part2_length) +{ + signed int exponents[39], exp; + signed int const *expptr; + struct mad_bitptr peek; + signed int bits_left, cachesz; + register mad_fixed_t *xrptr; + mad_fixed_t const *sfbound; + register unsigned long bitcache; + + bits_left = (signed) channel->part2_3_length - (signed) part2_length; + if (bits_left < 0) + return MAD_ERROR_BADPART3LEN; + + III_exponents(channel, sfbwidth, exponents); + + peek = *ptr; + mad_bit_skip(ptr, bits_left); + + /* align bit reads to byte boundaries */ + cachesz = mad_bit_bitsleft(&peek); + cachesz += ((32 - 1 - 24) + (24 - cachesz)) & ~7; + + bitcache = mad_bit_read(&peek, cachesz); + bits_left -= cachesz; + + xrptr = &xr[0]; + + /* big_values */ + { + unsigned int region, rcount; + struct hufftable const *entry; + union huffpair const *table; + unsigned int linbits, startbits, big_values, reqhits; + mad_fixed_t reqcache[16]; + + sfbound = xrptr + *sfbwidth++; + rcount = channel->region0_count + 1; + + entry = &mad_huff_pair_table[channel->table_select[region = 0]]; + table = entry->table; + linbits = entry->linbits; + startbits = entry->startbits; + + if (table == 0) + return MAD_ERROR_BADHUFFTABLE; + + expptr = &exponents[0]; + exp = *expptr++; + reqhits = 0; + + big_values = channel->big_values; + + while (big_values-- && cachesz + bits_left > 0) { + union huffpair const *pair; + unsigned int clumpsz, value; + register mad_fixed_t requantized; + + if (xrptr == sfbound) { + sfbound += *sfbwidth++; + + /* change table if region boundary */ + + if (--rcount == 0) { + if (region == 0) + rcount = channel->region1_count + 1; + else + rcount = 0; /* all remaining */ + + entry = &mad_huff_pair_table[channel->table_select[++region]]; + table = entry->table; + linbits = entry->linbits; + startbits = entry->startbits; + + if (table == 0) + return MAD_ERROR_BADHUFFTABLE; + } + + if (exp != *expptr) { + exp = *expptr; + reqhits = 0; + } + + ++expptr; + } + + if (cachesz < 21) { + unsigned int bits; + + bits = ((32 - 1 - 21) + (21 - cachesz)) & ~7; + bitcache = (bitcache << bits) | mad_bit_read(&peek, bits); + cachesz += bits; + bits_left -= bits; + } + + /* hcod (0..19) */ + + clumpsz = startbits; + pair = &table[MASK(bitcache, cachesz, clumpsz)]; + + while (!pair->final) { + cachesz -= clumpsz; + + clumpsz = pair->ptr.bits; + pair = &table[pair->ptr.offset + MASK(bitcache, cachesz, clumpsz)]; + } + + cachesz -= pair->value.hlen; + + if (linbits) { + /* x (0..14) */ + + value = pair->value.x; + + switch (value) { + case 0: + xrptr[0] = 0; + break; + + case 15: + if (cachesz < linbits + 2) { + bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); + cachesz += 16; + bits_left -= 16; + } + + value += MASK(bitcache, cachesz, linbits); + cachesz -= linbits; + + requantized = III_requantize(value, exp); + goto x_final; + + default: + if (reqhits & (1 << value)) + requantized = reqcache[value]; + else { + reqhits |= (1 << value); + requantized = reqcache[value] = III_requantize(value, exp); + } + + x_final: + xrptr[0] = MASK1BIT(bitcache, cachesz--) ? + -requantized : requantized; + } + + /* y (0..14) */ + + value = pair->value.y; + + switch (value) { + case 0: + xrptr[1] = 0; + break; + + case 15: + if (cachesz < linbits + 1) { + bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); + cachesz += 16; + bits_left -= 16; + } + + value += MASK(bitcache, cachesz, linbits); + cachesz -= linbits; + + requantized = III_requantize(value, exp); + goto y_final; + + default: + if (reqhits & (1 << value)) + requantized = reqcache[value]; + else { + reqhits |= (1 << value); + requantized = reqcache[value] = III_requantize(value, exp); + } + + y_final: + xrptr[1] = MASK1BIT(bitcache, cachesz--) ? + -requantized : requantized; + } + } + else { + /* x (0..1) */ + + value = pair->value.x; + + if (value == 0) + xrptr[0] = 0; + else { + if (reqhits & (1 << value)) + requantized = reqcache[value]; + else { + reqhits |= (1 << value); + requantized = reqcache[value] = III_requantize(value, exp); + } + + xrptr[0] = MASK1BIT(bitcache, cachesz--) ? + -requantized : requantized; + } + + /* y (0..1) */ + + value = pair->value.y; + + if (value == 0) + xrptr[1] = 0; + else { + if (reqhits & (1 << value)) + requantized = reqcache[value]; + else { + reqhits |= (1 << value); + requantized = reqcache[value] = III_requantize(value, exp); + } + + xrptr[1] = MASK1BIT(bitcache, cachesz--) ? + -requantized : requantized; + } + } + + xrptr += 2; + } + } + + if (cachesz + bits_left < 0) + return MAD_ERROR_BADHUFFDATA; /* big_values overrun */ + + /* count1 */ + { + union huffquad const *table; + register mad_fixed_t requantized; + + table = mad_huff_quad_table[channel->flags & count1table_select]; + + requantized = III_requantize(1, exp); + + while (cachesz + bits_left > 0 && xrptr <= &xr[572]) { + union huffquad const *quad; + + /* hcod (1..6) */ + + if (cachesz < 10) { + bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); + cachesz += 16; + bits_left -= 16; + } + + quad = &table[MASK(bitcache, cachesz, 4)]; + + /* quad tables guaranteed to have at most one extra lookup */ + if (!quad->final) { + cachesz -= 4; + + quad = &table[quad->ptr.offset + + MASK(bitcache, cachesz, quad->ptr.bits)]; + } + + cachesz -= quad->value.hlen; + + if (xrptr == sfbound) { + sfbound += *sfbwidth++; + + if (exp != *expptr) { + exp = *expptr; + requantized = III_requantize(1, exp); + } + + ++expptr; + } + + /* v (0..1) */ + + xrptr[0] = quad->value.v ? + (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; + + /* w (0..1) */ + + xrptr[1] = quad->value.w ? + (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; + + xrptr += 2; + + if (xrptr == sfbound) { + sfbound += *sfbwidth++; + + if (exp != *expptr) { + exp = *expptr; + requantized = III_requantize(1, exp); + } + + ++expptr; + } + + /* x (0..1) */ + + xrptr[0] = quad->value.x ? + (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; + + /* y (0..1) */ + + xrptr[1] = quad->value.y ? + (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; + + xrptr += 2; + } + + if (cachesz + bits_left < 0) { +# if 0 && defined(DEBUG) + fprintf(stderr, "huffman count1 overrun (%d bits)\n", + -(cachesz + bits_left)); +# endif + + /* technically the bitstream is misformatted, but apparently + some encoders are just a bit sloppy with stuffing bits */ + + xrptr -= 4; + } + } + + assert(-bits_left <= MAD_BUFFER_GUARD * CHAR_BIT); + +# if 0 && defined(DEBUG) + if (bits_left < 0) + fprintf(stderr, "read %d bits too many\n", -bits_left); + else if (cachesz + bits_left > 0) + fprintf(stderr, "%d stuffing bits\n", cachesz + bits_left); +# endif + + /* rzero */ + while (xrptr < &xr[576]) { + xrptr[0] = 0; + xrptr[1] = 0; + + xrptr += 2; + } + + return 0; +} + +# undef MASK +# undef MASK1BIT + +/* + * NAME: III_reorder() + * DESCRIPTION: reorder frequency lines of a short block into subband order + */ +static +void III_reorder(mad_fixed_t xr[576], struct channel const *channel, + unsigned char const sfbwidth[39]) +{ + mad_fixed_t tmp[32][3][6]; + unsigned int sb, l, sfbi, f, w, sbw[3], sw[3]; + + /* this is probably wrong for 8000 Hz mixed blocks */ + + if (channel->flags & mixed_block_flag) + sb = 2, sfbi = 3 * 3; + else + sb = 0, sfbi = 0; + + for (w = 0; w < 3; ++w) { + sbw[w] = sb; + sw[w] = 0; + } + + f = sfbwidth[sfbi]; + w = 0; + + for (l = 18 * sb; l < 576; ++l) { + tmp[sbw[w]][w][sw[w]++] = xr[l]; + + if (sw[w] == 6) { + sw[w] = 0; + ++sbw[w]; + } + + if (--f == 0) { + if (++w == 3) + w = 0; + + f = sfbwidth[++sfbi]; + } + } + + memcpy(&xr[18 * sb], &tmp[sb], (576 - 18 * sb) * sizeof(mad_fixed_t)); +} + +/* + * NAME: III_stereo() + * DESCRIPTION: perform joint stereo processing on a granule + */ +static +enum mad_error III_stereo(mad_fixed_t xr[2][576], + struct granule const *granule, + struct mad_header *header, + unsigned char const *sfbwidth) +{ + short modes[39]; + unsigned int sfbi, l, n, i; + + enum { + i_stereo = 0x1, + ms_stereo = 0x2 + }; + + if (granule->ch[0].block_type != + granule->ch[1].block_type || + (granule->ch[0].flags & mixed_block_flag) != + (granule->ch[1].flags & mixed_block_flag)) + return MAD_ERROR_BADSTEREO; + + for (i = 0; i < 39; ++i) + modes[i] = header->mode_extension; + + /* intensity stereo */ + + if (header->mode_extension & i_stereo) { + struct channel const *right_ch = &granule->ch[1]; + mad_fixed_t const *right_xr = xr[1]; + unsigned int is_pos; + + header->flags |= MAD_FLAG_I_STEREO; + + /* first determine which scalefactor bands are to be processed */ + + if (right_ch->block_type == 2) { + unsigned int lower, start, max, bound[3], w; + + lower = start = max = bound[0] = bound[1] = bound[2] = 0; + + sfbi = l = 0; + + if (right_ch->flags & mixed_block_flag) { + while (l < 36) { + n = sfbwidth[sfbi++]; + + for (i = 0; i < n; ++i) { + if (right_xr[i]) { + lower = sfbi; + break; + } + } + + right_xr += n; + l += n; + } + + start = sfbi; + } + + w = 0; + while (l < 576) { + n = sfbwidth[sfbi++]; + + for (i = 0; i < n; ++i) { + if (right_xr[i]) { + max = bound[w] = sfbi; + break; + } + } + + right_xr += n; + l += n; + w = (w + 1) % 3; + } + + if (max) + lower = start; + + /* long blocks */ + + for (i = 0; i < lower; ++i) + modes[i] = header->mode_extension & ~i_stereo; + + /* short blocks */ + + w = 0; + for (i = start; i < max; ++i) { + if (i < bound[w]) + modes[i] = header->mode_extension & ~i_stereo; + + w = (w + 1) % 3; + } + } + else { /* right_ch->block_type != 2 */ + unsigned int bound; + + bound = 0; + for (sfbi = l = 0; l < 576; l += n) { + n = sfbwidth[sfbi++]; + + for (i = 0; i < n; ++i) { + if (right_xr[i]) { + bound = sfbi; + break; + } + } + + right_xr += n; + } + + for (i = 0; i < bound; ++i) + modes[i] = header->mode_extension & ~i_stereo; + } + + /* now do the actual processing */ + + if (header->flags & MAD_FLAG_LSF_EXT) { + unsigned char const *illegal_pos = granule[1].ch[1].scalefac; + mad_fixed_t const *lsf_scale; + + /* intensity_scale */ + lsf_scale = is_lsf_table[right_ch->scalefac_compress & 0x1]; + + for (sfbi = l = 0; l < 576; ++sfbi, l += n) { + n = sfbwidth[sfbi]; + + if (!(modes[sfbi] & i_stereo)) + continue; + + if (illegal_pos[sfbi]) { + modes[sfbi] &= ~i_stereo; + continue; + } + + is_pos = right_ch->scalefac[sfbi]; + + for (i = 0; i < n; ++i) { + register mad_fixed_t left; + + left = xr[0][l + i]; + + if (is_pos == 0) + xr[1][l + i] = left; + else { + register mad_fixed_t opposite; + + opposite = mad_f_mul(left, lsf_scale[(is_pos - 1) / 2]); + + if (is_pos & 1) { + xr[0][l + i] = opposite; + xr[1][l + i] = left; + } + else + xr[1][l + i] = opposite; + } + } + } + } + else { /* !(header->flags & MAD_FLAG_LSF_EXT) */ + for (sfbi = l = 0; l < 576; ++sfbi, l += n) { + n = sfbwidth[sfbi]; + + if (!(modes[sfbi] & i_stereo)) + continue; + + is_pos = right_ch->scalefac[sfbi]; + + if (is_pos >= 7) { /* illegal intensity position */ + modes[sfbi] &= ~i_stereo; + continue; + } + + for (i = 0; i < n; ++i) { + register mad_fixed_t left; + + left = xr[0][l + i]; + + xr[0][l + i] = mad_f_mul(left, is_table[ is_pos]); + xr[1][l + i] = mad_f_mul(left, is_table[6 - is_pos]); + } + } + } + } + + /* middle/side stereo */ + + if (header->mode_extension & ms_stereo) { + register mad_fixed_t invsqrt2; + + header->flags |= MAD_FLAG_MS_STEREO; + + invsqrt2 = root_table[3 + -2]; + + for (sfbi = l = 0; l < 576; ++sfbi, l += n) { + n = sfbwidth[sfbi]; + + if (modes[sfbi] != ms_stereo) + continue; + + for (i = 0; i < n; ++i) { + register mad_fixed_t m, s; + + m = xr[0][l + i]; + s = xr[1][l + i]; + + xr[0][l + i] = mad_f_mul(m + s, invsqrt2); /* l = (m + s) / sqrt(2) */ + xr[1][l + i] = mad_f_mul(m - s, invsqrt2); /* r = (m - s) / sqrt(2) */ + } + } + } + + return 0; +} + +/* + * NAME: III_aliasreduce() + * DESCRIPTION: perform frequency line alias reduction + */ +static +void III_aliasreduce(mad_fixed_t xr[576], int lines) +{ + mad_fixed_t const *bound; + int i; + + bound = &xr[lines]; + for (xr += 18; xr < bound; xr += 18) { + for (i = 0; i < 8; ++i) { + register mad_fixed_t *aptr, *bptr, a, b; + register mad_fixed64hi_t hi; + register mad_fixed64lo_t lo; + + aptr = &xr[-1 - i]; + bptr = &xr[ i]; + + a = *aptr; + b = *bptr; + +# if defined(ASO_ZEROCHECK) + if (a | b) { +# endif + MAD_F_ML0(hi, lo, a, cs[i]); + MAD_F_MLA(hi, lo, -b, ca[i]); + + *aptr = MAD_F_MLZ(hi, lo); + + MAD_F_ML0(hi, lo, b, cs[i]); + MAD_F_MLA(hi, lo, a, ca[i]); + + *bptr = MAD_F_MLZ(hi, lo); +# if defined(ASO_ZEROCHECK) + } +# endif + } + } +} + +# if defined(ASO_IMDCT) +void III_imdct_l(mad_fixed_t const [18], mad_fixed_t [36], unsigned int); +# else +/* + * NAME: imdct36 + * DESCRIPTION: perform X[18]->x[36] IMDCT + */ +static inline +void imdct36(mad_fixed_t const X[18], mad_fixed_t x[36]) +{ + mad_fixed_t t0, t1, t2, t3, t4, t5, t6, t7; + mad_fixed_t t8, t9, t10, t11, t12, t13, t14, t15; + register mad_fixed64hi_t hi; + register mad_fixed64lo_t lo; + + MAD_F_ML0(hi, lo, X[4], MAD_F(0x0ec835e8)); + MAD_F_MLA(hi, lo, X[13], MAD_F(0x061f78aa)); + + t6 = MAD_F_MLZ(hi, lo); + + MAD_F_MLA(hi, lo, (t14 = X[1] - X[10]), -MAD_F(0x061f78aa)); + MAD_F_MLA(hi, lo, (t15 = X[7] + X[16]), -MAD_F(0x0ec835e8)); + + t0 = MAD_F_MLZ(hi, lo); + + MAD_F_MLA(hi, lo, (t8 = X[0] - X[11] - X[12]), MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, (t9 = X[2] - X[9] - X[14]), MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, (t10 = X[3] - X[8] - X[15]), -MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, (t11 = X[5] - X[6] - X[17]), -MAD_F(0x0fdcf549)); + + x[7] = MAD_F_MLZ(hi, lo); + x[10] = -x[7]; + + MAD_F_ML0(hi, lo, t8, -MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, t9, MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, t10, MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, t11, -MAD_F(0x09bd7ca0)); + + x[19] = x[34] = MAD_F_MLZ(hi, lo) - t0; + + t12 = X[0] - X[3] + X[8] - X[11] - X[12] + X[15]; + t13 = X[2] + X[5] - X[6] - X[9] - X[14] - X[17]; + + MAD_F_ML0(hi, lo, t12, -MAD_F(0x0ec835e8)); + MAD_F_MLA(hi, lo, t13, MAD_F(0x061f78aa)); + + x[22] = x[31] = MAD_F_MLZ(hi, lo) + t0; + + MAD_F_ML0(hi, lo, X[1], -MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, X[7], MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, X[10], -MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, X[16], MAD_F(0x0cb19346)); + + t1 = MAD_F_MLZ(hi, lo) + t6; + + MAD_F_ML0(hi, lo, X[0], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[11], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0f9ee890)); + + x[6] = MAD_F_MLZ(hi, lo) + t1; + x[11] = -x[6]; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[2], -MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[17], MAD_F(0x04cfb0e2)); + + x[23] = x[30] = MAD_F_MLZ(hi, lo) + t1; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[11], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0acf37ad)); + + x[18] = x[35] = MAD_F_MLZ(hi, lo) - t1; + + MAD_F_ML0(hi, lo, X[4], MAD_F(0x061f78aa)); + MAD_F_MLA(hi, lo, X[13], -MAD_F(0x0ec835e8)); + + t7 = MAD_F_MLZ(hi, lo); + + MAD_F_MLA(hi, lo, X[1], -MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, X[7], MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, X[10], MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, X[16], -MAD_F(0x09bd7ca0)); + + t2 = MAD_F_MLZ(hi, lo); + + MAD_F_MLA(hi, lo, X[0], MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[12], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[17], MAD_F(0x0f426cb5)); + + x[5] = MAD_F_MLZ(hi, lo); + x[12] = -x[5]; + + MAD_F_ML0(hi, lo, X[0], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[2], -MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[11], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0bcbe352)); + + x[0] = MAD_F_MLZ(hi, lo) + t2; + x[17] = -x[0]; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[2], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[14], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x03768962)); + + x[24] = x[29] = MAD_F_MLZ(hi, lo) + t2; + + MAD_F_ML0(hi, lo, X[1], -MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, X[7], -MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, X[10], MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, X[16], MAD_F(0x0fdcf549)); + + t3 = MAD_F_MLZ(hi, lo) + t7; + + MAD_F_ML0(hi, lo, X[0], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[12], MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0ffc19fd)); + + x[8] = MAD_F_MLZ(hi, lo) + t3; + x[9] = -x[8]; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[14], -MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[17], MAD_F(0x07635284)); + + x[21] = x[32] = MAD_F_MLZ(hi, lo) + t3; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[12], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0898c779)); + + x[20] = x[33] = MAD_F_MLZ(hi, lo) - t3; + + MAD_F_ML0(hi, lo, t14, -MAD_F(0x0ec835e8)); + MAD_F_MLA(hi, lo, t15, MAD_F(0x061f78aa)); + + t4 = MAD_F_MLZ(hi, lo) - t7; + + MAD_F_ML0(hi, lo, t12, MAD_F(0x061f78aa)); + MAD_F_MLA(hi, lo, t13, MAD_F(0x0ec835e8)); + + x[4] = MAD_F_MLZ(hi, lo) + t4; + x[13] = -x[4]; + + MAD_F_ML0(hi, lo, t8, MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, t9, -MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, t10, MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, t11, -MAD_F(0x0cb19346)); + + x[1] = MAD_F_MLZ(hi, lo) + t4; + x[16] = -x[1]; + + MAD_F_ML0(hi, lo, t8, -MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, t9, -MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, t10, -MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, t11, -MAD_F(0x0216a2a2)); + + x[25] = x[28] = MAD_F_MLZ(hi, lo) + t4; + + MAD_F_ML0(hi, lo, X[1], -MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, X[7], -MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, X[10], -MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, X[16], -MAD_F(0x0216a2a2)); + + t5 = MAD_F_MLZ(hi, lo) - t6; + + MAD_F_ML0(hi, lo, X[0], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[12], MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[14], -MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0d7e8807)); + + x[2] = MAD_F_MLZ(hi, lo) + t5; + x[15] = -x[2]; + + MAD_F_ML0(hi, lo, X[0], MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[11], MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[17], MAD_F(0x0e313245)); + + x[3] = MAD_F_MLZ(hi, lo) + t5; + x[14] = -x[3]; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[2], -MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[14], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x00b2aa3e)); + + x[26] = x[27] = MAD_F_MLZ(hi, lo) + t5; +} + +/* + * NAME: III_imdct_l() + * DESCRIPTION: perform IMDCT and windowing for long blocks + */ +static +void III_imdct_l(mad_fixed_t const X[18], mad_fixed_t z[36], + unsigned int block_type) +{ + unsigned int i; + + /* IMDCT */ + + imdct36(X, z); + + /* windowing */ + + switch (block_type) { + case 0: /* normal window */ +# if defined(ASO_INTERLEAVE1) + { + register mad_fixed_t tmp1, tmp2; + + tmp1 = window_l[0]; + tmp2 = window_l[1]; + + for (i = 0; i < 34; i += 2) { + z[i + 0] = mad_f_mul(z[i + 0], tmp1); + tmp1 = window_l[i + 2]; + z[i + 1] = mad_f_mul(z[i + 1], tmp2); + tmp2 = window_l[i + 3]; + } + + z[34] = mad_f_mul(z[34], tmp1); + z[35] = mad_f_mul(z[35], tmp2); + } +# elif defined(ASO_INTERLEAVE2) + { + register mad_fixed_t tmp1, tmp2; + + tmp1 = z[0]; + tmp2 = window_l[0]; + + for (i = 0; i < 35; ++i) { + z[i] = mad_f_mul(tmp1, tmp2); + tmp1 = z[i + 1]; + tmp2 = window_l[i + 1]; + } + + z[35] = mad_f_mul(tmp1, tmp2); + } +# elif 1 + for (i = 0; i < 36; i += 4) { + z[i + 0] = mad_f_mul(z[i + 0], window_l[i + 0]); + z[i + 1] = mad_f_mul(z[i + 1], window_l[i + 1]); + z[i + 2] = mad_f_mul(z[i + 2], window_l[i + 2]); + z[i + 3] = mad_f_mul(z[i + 3], window_l[i + 3]); + } +# else + for (i = 0; i < 36; ++i) z[i] = mad_f_mul(z[i], window_l[i]); +# endif + break; + + case 1: /* start block */ + for (i = 0; i < 18; ++i) z[i] = mad_f_mul(z[i], window_l[i]); + /* (i = 18; i < 24; ++i) z[i] unchanged */ + for (i = 24; i < 30; ++i) z[i] = mad_f_mul(z[i], window_s[i - 18]); + for (i = 30; i < 36; ++i) z[i] = 0; + break; + + case 3: /* stop block */ + for (i = 0; i < 6; ++i) z[i] = 0; + for (i = 6; i < 12; ++i) z[i] = mad_f_mul(z[i], window_s[i - 6]); + /* (i = 12; i < 18; ++i) z[i] unchanged */ + for (i = 18; i < 36; ++i) z[i] = mad_f_mul(z[i], window_l[i]); + break; + } +} +# endif /* ASO_IMDCT */ + +/* + * NAME: III_imdct_s() + * DESCRIPTION: perform IMDCT and windowing for short blocks + */ +static +void III_imdct_s(mad_fixed_t const X[18], mad_fixed_t z[36]) +{ + mad_fixed_t y[36], *yptr; + mad_fixed_t const *wptr; + int w, i; + register mad_fixed64hi_t hi; + register mad_fixed64lo_t lo; + + /* IMDCT */ + + yptr = &y[0]; + + for (w = 0; w < 3; ++w) { + register mad_fixed_t const (*s)[6]; + + s = imdct_s; + + for (i = 0; i < 3; ++i) { + MAD_F_ML0(hi, lo, X[0], (*s)[0]); + MAD_F_MLA(hi, lo, X[1], (*s)[1]); + MAD_F_MLA(hi, lo, X[2], (*s)[2]); + MAD_F_MLA(hi, lo, X[3], (*s)[3]); + MAD_F_MLA(hi, lo, X[4], (*s)[4]); + MAD_F_MLA(hi, lo, X[5], (*s)[5]); + + yptr[i + 0] = MAD_F_MLZ(hi, lo); + yptr[5 - i] = -yptr[i + 0]; + + ++s; + + MAD_F_ML0(hi, lo, X[0], (*s)[0]); + MAD_F_MLA(hi, lo, X[1], (*s)[1]); + MAD_F_MLA(hi, lo, X[2], (*s)[2]); + MAD_F_MLA(hi, lo, X[3], (*s)[3]); + MAD_F_MLA(hi, lo, X[4], (*s)[4]); + MAD_F_MLA(hi, lo, X[5], (*s)[5]); + + yptr[ i + 6] = MAD_F_MLZ(hi, lo); + yptr[11 - i] = yptr[i + 6]; + + ++s; + } + + yptr += 12; + X += 6; + } + + /* windowing, overlapping and concatenation */ + + yptr = &y[0]; + wptr = &window_s[0]; + + for (i = 0; i < 6; ++i) { + z[i + 0] = 0; + z[i + 6] = mad_f_mul(yptr[ 0 + 0], wptr[0]); + + MAD_F_ML0(hi, lo, yptr[ 0 + 6], wptr[6]); + MAD_F_MLA(hi, lo, yptr[12 + 0], wptr[0]); + + z[i + 12] = MAD_F_MLZ(hi, lo); + + MAD_F_ML0(hi, lo, yptr[12 + 6], wptr[6]); + MAD_F_MLA(hi, lo, yptr[24 + 0], wptr[0]); + + z[i + 18] = MAD_F_MLZ(hi, lo); + + z[i + 24] = mad_f_mul(yptr[24 + 6], wptr[6]); + z[i + 30] = 0; + + ++yptr; + ++wptr; + } +} + +/* + * NAME: III_overlap() + * DESCRIPTION: perform overlap-add of windowed IMDCT outputs + */ +static +void III_overlap(mad_fixed_t const output[36], mad_fixed_t overlap[18], + mad_fixed_t sample[18][32], unsigned int sb) +{ + unsigned int i; + +# if defined(ASO_INTERLEAVE2) + { + register mad_fixed_t tmp1, tmp2; + + tmp1 = overlap[0]; + tmp2 = overlap[1]; + + for (i = 0; i < 16; i += 2) { + sample[i + 0][sb] = output[i + 0] + tmp1; + overlap[i + 0] = output[i + 0 + 18]; + tmp1 = overlap[i + 2]; + + sample[i + 1][sb] = output[i + 1] + tmp2; + overlap[i + 1] = output[i + 1 + 18]; + tmp2 = overlap[i + 3]; + } + + sample[16][sb] = output[16] + tmp1; + overlap[16] = output[16 + 18]; + sample[17][sb] = output[17] + tmp2; + overlap[17] = output[17 + 18]; + } +# elif 0 + for (i = 0; i < 18; i += 2) { + sample[i + 0][sb] = output[i + 0] + overlap[i + 0]; + overlap[i + 0] = output[i + 0 + 18]; + + sample[i + 1][sb] = output[i + 1] + overlap[i + 1]; + overlap[i + 1] = output[i + 1 + 18]; + } +# else + for (i = 0; i < 18; ++i) { + sample[i][sb] = output[i] + overlap[i]; + overlap[i] = output[i + 18]; + } +# endif +} + +/* + * NAME: III_overlap_z() + * DESCRIPTION: perform "overlap-add" of zero IMDCT outputs + */ +static inline +void III_overlap_z(mad_fixed_t overlap[18], + mad_fixed_t sample[18][32], unsigned int sb) +{ + unsigned int i; + +# if defined(ASO_INTERLEAVE2) + { + register mad_fixed_t tmp1, tmp2; + + tmp1 = overlap[0]; + tmp2 = overlap[1]; + + for (i = 0; i < 16; i += 2) { + sample[i + 0][sb] = tmp1; + overlap[i + 0] = 0; + tmp1 = overlap[i + 2]; + + sample[i + 1][sb] = tmp2; + overlap[i + 1] = 0; + tmp2 = overlap[i + 3]; + } + + sample[16][sb] = tmp1; + overlap[16] = 0; + sample[17][sb] = tmp2; + overlap[17] = 0; + } +# else + for (i = 0; i < 18; ++i) { + sample[i][sb] = overlap[i]; + overlap[i] = 0; + } +# endif +} + +/* + * NAME: III_freqinver() + * DESCRIPTION: perform subband frequency inversion for odd sample lines + */ +static +void III_freqinver(mad_fixed_t sample[18][32], unsigned int sb) +{ + unsigned int i; + +# if 1 || defined(ASO_INTERLEAVE1) || defined(ASO_INTERLEAVE2) + { + register mad_fixed_t tmp1, tmp2; + + tmp1 = sample[1][sb]; + tmp2 = sample[3][sb]; + + for (i = 1; i < 13; i += 4) { + sample[i + 0][sb] = -tmp1; + tmp1 = sample[i + 4][sb]; + sample[i + 2][sb] = -tmp2; + tmp2 = sample[i + 6][sb]; + } + + sample[13][sb] = -tmp1; + tmp1 = sample[17][sb]; + sample[15][sb] = -tmp2; + sample[17][sb] = -tmp1; + } +# else + for (i = 1; i < 18; i += 2) + sample[i][sb] = -sample[i][sb]; +# endif +} + +/* + * NAME: III_decode() + * DESCRIPTION: decode frame main_data + */ +static +int III_decode(struct mad_bitptr *ptr, struct mad_frame *frame, + struct sideinfo *si, unsigned int nch) +{ + struct mad_header *header = &frame->header; + unsigned int sfreqi, ngr, gr; + + { + unsigned int sfreq; + + sfreq = header->samplerate; + if (header->flags & MAD_FLAG_MPEG_2_5_EXT) + sfreq *= 2; + + /* 48000 => 0, 44100 => 1, 32000 => 2, + 24000 => 3, 22050 => 4, 16000 => 5 */ + sfreqi = ((sfreq >> 7) & 0x000f) + + ((sfreq >> 15) & 0x0001) - 8; + + if (header->flags & MAD_FLAG_MPEG_2_5_EXT) + sfreqi += 3; + } + + /* scalefactors, Huffman decoding, requantization */ + + ngr = (header->flags & MAD_FLAG_LSF_EXT) ? 1 : 2; + + for (gr = 0; gr < ngr; ++gr) { + struct granule *granule = &si->gr[gr]; + unsigned char const *sfbwidth = 0; + mad_fixed_t xr[2][576]; + unsigned int ch; + enum mad_error error; + + for (ch = 0; ch < nch; ++ch) { + struct channel *channel = &granule->ch[ch]; + unsigned int part2_length; + + sfbwidth = sfbwidth_table[sfreqi].l; + if (channel->block_type == 2) { + sfbwidth = (channel->flags & mixed_block_flag) ? + sfbwidth_table[sfreqi].m : sfbwidth_table[sfreqi].s; + } + + if (header->flags & MAD_FLAG_LSF_EXT) { + part2_length = III_scalefactors_lsf(ptr, channel, + ch == 0 ? 0 : &si->gr[1].ch[1], + header->mode_extension); + } + else { + part2_length = III_scalefactors(ptr, channel, &si->gr[0].ch[ch], + gr == 0 ? 0 : si->scfsi[ch]); + } + + error = III_huffdecode(ptr, xr[ch], channel, sfbwidth, part2_length); + if (error) + return error; + } + + /* joint stereo processing */ + + if (header->mode == MAD_MODE_JOINT_STEREO && header->mode_extension) { + error = III_stereo(xr, granule, header, sfbwidth); + if (error) + return error; + } + + /* reordering, alias reduction, IMDCT, overlap-add, frequency inversion */ + + for (ch = 0; ch < nch; ++ch) { + struct channel const *channel = &granule->ch[ch]; + mad_fixed_t (*sample)[32] = &frame->sbsample[ch][18 * gr]; + unsigned int sb, l, i, sblimit; + mad_fixed_t output[36]; + + if (channel->block_type == 2) { + III_reorder(xr[ch], channel, sfbwidth_table[sfreqi].s); + +# if !defined(OPT_STRICT) + /* + * According to ISO/IEC 11172-3, "Alias reduction is not applied for + * granules with block_type == 2 (short block)." However, other + * sources suggest alias reduction should indeed be performed on the + * lower two subbands of mixed blocks. Most other implementations do + * this, so by default we will too. + */ + if (channel->flags & mixed_block_flag) + III_aliasreduce(xr[ch], 36); +# endif + } + else + III_aliasreduce(xr[ch], 576); + + l = 0; + + /* subbands 0-1 */ + + if (channel->block_type != 2 || (channel->flags & mixed_block_flag)) { + unsigned int block_type; + + block_type = channel->block_type; + if (channel->flags & mixed_block_flag) + block_type = 0; + + /* long blocks */ + for (sb = 0; sb < 2; ++sb, l += 18) { + III_imdct_l(&xr[ch][l], output, block_type); + III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); + } + } + else { + /* short blocks */ + for (sb = 0; sb < 2; ++sb, l += 18) { + III_imdct_s(&xr[ch][l], output); + III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); + } + } + + III_freqinver(sample, 1); + + /* (nonzero) subbands 2-31 */ + + i = 576; + while (i > 36 && xr[ch][i - 1] == 0) + --i; + + sblimit = 32 - (576 - i) / 18; + + if (channel->block_type != 2) { + /* long blocks */ + for (sb = 2; sb < sblimit; ++sb, l += 18) { + III_imdct_l(&xr[ch][l], output, channel->block_type); + III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); + + if (sb & 1) + III_freqinver(sample, sb); + } + } + else { + /* short blocks */ + for (sb = 2; sb < sblimit; ++sb, l += 18) { + III_imdct_s(&xr[ch][l], output); + III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); + + if (sb & 1) + III_freqinver(sample, sb); + } + } + + /* remaining (zero) subbands */ + + for (sb = sblimit; sb < 32; ++sb) { + III_overlap_z((*frame->overlap)[ch][sb], sample, sb); + + if (sb & 1) + III_freqinver(sample, sb); + } + } + } + + return 0; +} + +/* + * NAME: layer->III() + * DESCRIPTION: decode a single Layer III frame + */ +int mad_layer_III(struct mad_stream *stream, struct mad_frame *frame) +{ + struct mad_header *header = &frame->header; + unsigned int nch, priv_bitlen, next_md_begin = 0; + unsigned int si_len, data_bitlen, md_len; + unsigned int frame_space, frame_used, frame_free; + struct mad_bitptr ptr; + struct sideinfo si; + enum mad_error error; + int result = 0; + + /* allocate Layer III dynamic structures */ + + if (stream->main_data == 0) { + stream->main_data = malloc(MAD_BUFFER_MDLEN); + if (stream->main_data == 0) { + stream->error = MAD_ERROR_NOMEM; + return -1; + } + } + + if (frame->overlap == 0) { + frame->overlap = calloc(2 * 32 * 18, sizeof(mad_fixed_t)); + if (frame->overlap == 0) { + stream->error = MAD_ERROR_NOMEM; + return -1; + } + } + + nch = MAD_NCHANNELS(header); + si_len = (header->flags & MAD_FLAG_LSF_EXT) ? + (nch == 1 ? 9 : 17) : (nch == 1 ? 17 : 32); + + /* check frame sanity */ + + if (stream->next_frame - mad_bit_nextbyte(&stream->ptr) < + (signed int) si_len) { + stream->error = MAD_ERROR_BADFRAMELEN; + stream->md_len = 0; + return -1; + } + + /* check CRC word */ + + if (header->flags & MAD_FLAG_PROTECTION) { + header->crc_check = + mad_bit_crc(stream->ptr, si_len * CHAR_BIT, header->crc_check); + + if (header->crc_check != header->crc_target && + !(frame->options & MAD_OPTION_IGNORECRC)) { + stream->error = MAD_ERROR_BADCRC; + result = -1; + } + } + + /* decode frame side information */ + + error = III_sideinfo(&stream->ptr, nch, header->flags & MAD_FLAG_LSF_EXT, + &si, &data_bitlen, &priv_bitlen); + if (error && result == 0) { + stream->error = error; + result = -1; + } + + header->flags |= priv_bitlen; + header->private_bits |= si.private_bits; + + /* find main_data of next frame */ + + { + struct mad_bitptr peek; + unsigned long header; + + mad_bit_init(&peek, stream->next_frame); + + header = mad_bit_read(&peek, 32); + if ((header & 0xffe60000L) /* syncword | layer */ == 0xffe20000L) { + if (!(header & 0x00010000L)) /* protection_bit */ + mad_bit_skip(&peek, 16); /* crc_check */ + + next_md_begin = + mad_bit_read(&peek, (header & 0x00080000L) /* ID */ ? 9 : 8); + } + + mad_bit_finish(&peek); + } + + /* find main_data of this frame */ + + frame_space = stream->next_frame - mad_bit_nextbyte(&stream->ptr); + + if (next_md_begin > si.main_data_begin + frame_space) + next_md_begin = 0; + + md_len = si.main_data_begin + frame_space - next_md_begin; + + frame_used = 0; + + if (si.main_data_begin == 0) { + ptr = stream->ptr; + stream->md_len = 0; + + frame_used = md_len; + } + else { + if (si.main_data_begin > stream->md_len) { + if (result == 0) { + stream->error = MAD_ERROR_BADDATAPTR; + result = -1; + } + } + else { + mad_bit_init(&ptr, + *stream->main_data + stream->md_len - si.main_data_begin); + + if (md_len > si.main_data_begin) { + assert(stream->md_len + md_len - + si.main_data_begin <= MAD_BUFFER_MDLEN); + + memcpy(*stream->main_data + stream->md_len, + mad_bit_nextbyte(&stream->ptr), + frame_used = md_len - si.main_data_begin); + stream->md_len += frame_used; + } + } + } + + frame_free = frame_space - frame_used; + + /* decode main_data */ + + if (result == 0) { + error = III_decode(&ptr, frame, &si, nch); + if (error) { + stream->error = error; + result = -1; + } + } + + /* designate ancillary bits */ + + stream->anc_ptr = ptr; + stream->anc_bitlen = md_len * CHAR_BIT - data_bitlen; + +# if 0 && defined(DEBUG) + fprintf(stderr, + "main_data_begin:%u, md_len:%u, frame_free:%u, " + "data_bitlen:%u, anc_bitlen: %u\n", + si.main_data_begin, md_len, frame_free, + data_bitlen, stream->anc_bitlen); +# endif + + /* preload main_data buffer with up to 511 bytes for next frame(s) */ + + if (frame_free >= next_md_begin) { + memcpy(*stream->main_data, + stream->next_frame - next_md_begin, next_md_begin); + stream->md_len = next_md_begin; + } + else { + if (md_len < si.main_data_begin) { + unsigned int extra; + + extra = si.main_data_begin - md_len; + if (extra + frame_free > next_md_begin) + extra = next_md_begin - frame_free; + + if (extra < stream->md_len) { + memmove(*stream->main_data, + *stream->main_data + stream->md_len - extra, extra); + stream->md_len = extra; + } + } + else + stream->md_len = 0; + + memcpy(*stream->main_data + stream->md_len, + stream->next_frame - frame_free, frame_free); + stream->md_len += frame_free; + } + + return result; +} diff --git a/core/multimedia/opieplayer/libmad/layer3.h b/core/multimedia/opieplayer/libmad/layer3.h new file mode 100644 index 0000000..1fd83e2 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/layer3.h @@ -0,0 +1,30 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_LAYER3_H +# define LIBMAD_LAYER3_H + +# include "stream.h" +# include "frame.h" + +int mad_layer_III(struct mad_stream *, struct mad_frame *); + +# endif diff --git a/core/multimedia/opieplayer/libmad/libmad.pro b/core/multimedia/opieplayer/libmad/libmad.pro new file mode 100644 index 0000000..e3f75b7 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/libmad.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += qt warn_on release +HEADERS = libmad_version.h fixed.h bit.h timer.h stream.h frame.h synth.h decoder.h \ + layer12.h layer3.h huffman.h libmad_global.h mad.h libmadplugin.h libmadpluginimpl.h +SOURCES = version.c fixed.c bit.c timer.c stream.c frame.c synth.c decoder.c \ + layer12.c layer3.c huffman.c libmadplugin.cpp libmadpluginimpl.cpp +TARGET = madplugin +DESTDIR = ../../plugins/codecs +INCLUDEPATH += $(QPEDIR)/include .. +DEPENDPATH += ../$(QPEDIR)/include .. +LIBS += -lqpe -lm +VERSION = 1.0.0 diff --git a/core/multimedia/opieplayer/libmad/libmad_global.h b/core/multimedia/opieplayer/libmad/libmad_global.h new file mode 100644 index 0000000..f2a2a71 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/libmad_global.h @@ -0,0 +1,45 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_GLOBAL_H +# define LIBMAD_GLOBAL_H + +/* conditional debugging */ + +# if defined(DEBUG) && defined(NDEBUG) +# error "cannot define both DEBUG and NDEBUG" +# endif + +# if defined(DEBUG) +# include +# endif + +/* conditional features */ + +# if defined(OPT_SPEED) && defined(OPT_ACCURACY) +# error "cannot optimize for both speed and accuracy" +# endif + +# if defined(OPT_SPEED) && !defined(OPT_SSO) +# define OPT_SSO 1 +# endif + +# endif diff --git a/core/multimedia/opieplayer/libmad/libmad_version.h b/core/multimedia/opieplayer/libmad/libmad_version.h new file mode 100644 index 0000000..f8ee1fa --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/libmad_version.h @@ -0,0 +1,47 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_VERSION_H +# define LIBMAD_VERSION_H + +# define MAD_VERSION_MAJOR 0 +# define MAD_VERSION_MINOR 13 +# define MAD_VERSION_PATCH 0 +# define MAD_VERSION_EXTRA " (beta)" + +# define MAD_VERSION_STRINGIZE(str) #str +# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num) + +# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) "." \ + MAD_VERSION_STRING(MAD_VERSION_MINOR) "." \ + MAD_VERSION_STRING(MAD_VERSION_PATCH) \ + MAD_VERSION_EXTRA + +# define MAD_PUBLISHYEAR "2000-2001" +# define MAD_AUTHOR "Robert Leslie" +# define MAD_EMAIL "rob@mars.org" + +extern char const mad_version[]; +extern char const mad_copyright[]; +extern char const mad_author[]; +extern char const mad_build[]; + +# endif diff --git a/core/multimedia/opieplayer/libmad/libmadplugin.cpp b/core/multimedia/opieplayer/libmad/libmadplugin.cpp new file mode 100644 index 0000000..b2b876f --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/libmadplugin.cpp @@ -0,0 +1,578 @@ +/********************************************************************** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define HAVE_MMAP + +#if defined(HAVE_MMAP) +# include +#endif +#include "libmadplugin.h" + + +extern "C" { +#include "mad.h" +} + + +#define MPEG_BUFFER_SIZE 65536 +//#define debugMsg(a) qDebug(a) +#define debugMsg(a) + + +class Input { +public: + char const *path; + int fd; +#if defined(HAVE_MMAP) + void *fdm; +#endif + unsigned char *data; + unsigned long length; + int eof; +}; + + +class Output { +public: + mad_fixed_t attenuate; + struct filter *filters; + unsigned int channels_in; + unsigned int channels_out; + unsigned int speed_in; + unsigned int speed_out; + const char *path; +}; + + +# if defined(HAVE_MMAP) +static void *map_file(int fd, unsigned long *length) +{ + void *fdm; + + *length += MAD_BUFFER_GUARD; + + fdm = mmap(0, *length, PROT_READ, MAP_SHARED, fd, 0); + if (fdm == MAP_FAILED) + return 0; + +# if defined(HAVE_MADVISE) + madvise(fdm, *length, MADV_SEQUENTIAL); +# endif + + return fdm; +} + + +static int unmap_file(void *fdm, unsigned long length) +{ + if (munmap(fdm, length) == -1) + return -1; + + return 0; +} +# endif + + +static inline QString tr( const char *str ) { + // Apparently this is okay from a plugin as it runs in the process space of the owner of the plugin + return qApp->translate( "MediaPlayer", str, "libmad strings for mp3 file info" ); +} + + +class LibMadPluginData { +public: + Input input; + Output output; + int bad_last_frame; + struct mad_stream stream; + struct mad_frame frame; + struct mad_synth synth; + bool flush; +}; + + +LibMadPlugin::LibMadPlugin() { + d = new LibMadPluginData; + d->input.fd = 0; +#if defined(HAVE_MMAP) + d->input.fdm = 0; +#endif + d->input.data = 0; + d->flush = TRUE; + info = tr( "No Song Open" ); +} + + +LibMadPlugin::~LibMadPlugin() { + close(); + delete d; +} + + +bool LibMadPlugin::isFileSupported( const QString& path ) { + debugMsg( "LibMadPlugin::isFileSupported" ); + + // Mpeg file extensions + // "mp2","mp3","m1v","m2v","m2s","mpg","vob","mpeg","ac3" + // Other media extensions + // "wav","mid","mod","s3m","ogg","avi","mov","sid" + + char *ext = strrchr( path.latin1(), '.' ); + + // Test file extension + if ( ext ) { + if ( strncasecmp(ext, ".mp2", 4) == 0 ) + return TRUE; + if ( strncasecmp(ext, ".mp3", 4) == 0 ) + return TRUE; + } + + return FALSE; +} + + +bool LibMadPlugin::open( const QString& path ) { + debugMsg( "LibMadPlugin::open" ); + + d->bad_last_frame = 0; + d->flush = TRUE; + info = QString( "" ); + + //qDebug( "Opening %s", path.latin1() ); + + d->input.path = path.latin1(); + d->input.fd = ::open( d->input.path, O_RDONLY ); + if (d->input.fd == -1) { + qDebug("error opening %s", d->input.path ); + return FALSE; + } + + printID3Tags(); + +#if defined(HAVE_MMAP) + struct stat stat; + if (fstat(d->input.fd, &stat) == -1) { + qDebug("error calling fstat"); return FALSE; + } + if (S_ISREG(stat.st_mode) && stat.st_size > 0) { + d->input.length = stat.st_size; + d->input.fdm = map_file(d->input.fd, &d->input.length); + if (d->input.fdm == 0) { + qDebug("error mmapping file"); return FALSE; + } + d->input.data = (unsigned char *)d->input.fdm; + } +#endif + + if (d->input.data == 0) { + d->input.data = (unsigned char *)malloc(MPEG_BUFFER_SIZE); + if (d->input.data == 0) { + qDebug("error allocating input buffer"); + return FALSE; + } + d->input.length = 0; + } + + d->input.eof = 0; + + mad_stream_init(&d->stream); + mad_frame_init(&d->frame); + mad_synth_init(&d->synth); + + return TRUE; +} + + +bool LibMadPlugin::close() { + debugMsg( "LibMadPlugin::close" ); + + int result = TRUE; + + mad_synth_finish(&d->synth); + mad_frame_finish(&d->frame); + mad_stream_finish(&d->stream); + +#if defined(HAVE_MMAP) + if (d->input.fdm) { + if (unmap_file(d->input.fdm, d->input.length) == -1) { + qDebug("error munmapping file"); + result = FALSE; + } + d->input.fdm = 0; + d->input.data = 0; + } +#endif + + if (d->input.data) { + free(d->input.data); + d->input.data = 0; + } + + if (::close(d->input.fd) == -1) { + qDebug("error closing file %s", d->input.path); + result = FALSE; + } + + d->input.fd = 0; + + return result; +} + + +bool LibMadPlugin::isOpen() { + debugMsg( "LibMadPlugin::isOpen" ); + return ( d->input.fd != 0 ); +} + + +int LibMadPlugin::audioStreams() { + debugMsg( "LibMadPlugin::audioStreams" ); + return 1; +} + + +int LibMadPlugin::audioChannels( int ) { + debugMsg( "LibMadPlugin::audioChannels" ); +/* + long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); + qDebug( "LibMadPlugin::audioChannels: %i", d->frame.header.mode > 0 ? 2 : 1 ); + return d->frame.header.mode > 0 ? 2 : 1; +*/ + return 2; +} + + +int LibMadPlugin::audioFrequency( int ) { + debugMsg( "LibMadPlugin::audioFrequency" ); + long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); + qDebug( "LibMadPlugin::audioFrequency: %i", d->frame.header.samplerate ); + return d->frame.header.samplerate; +} + + +int LibMadPlugin::audioSamples( int ) { + debugMsg( "LibMadPlugin::audioSamples" ); +/* + long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); + mad_header_decode( (struct mad_header *)&d->frame.header, &d->stream ); + qDebug( "LibMadPlugin::audioSamples: %i*%i", d->frame.header.duration.seconds, d->frame.header.samplerate ); + return d->frame.header.duration.seconds * d->frame.header.samplerate; +*/ + return 10000000; +} + + +bool LibMadPlugin::audioSetSample( long, int ) { + debugMsg( "LibMadPlugin::audioSetSample" ); + return FALSE; +} + + +long LibMadPlugin::audioGetSample( int ) { + debugMsg( "LibMadPlugin::audioGetSample" ); + return 0; +} + +/* +bool LibMadPlugin::audioReadSamples( short *, int, long, int ) { + debugMsg( "LibMadPlugin::audioReadSamples" ); + return FALSE; +} + + +bool LibMadPlugin::audioReReadSamples( short *, int, long, int ) { + debugMsg( "LibMadPlugin::audioReReadSamples" ); + return FALSE; +} +*/ + +bool LibMadPlugin::read() { + debugMsg( "LibMadPlugin::read" ); + int len; + + if (d->input.eof) + return FALSE; + +#if defined(HAVE_MMAP) + if (d->input.fdm) { + unsigned long skip = 0; + + if (d->stream.next_frame) { + struct stat stat; + + if (fstat(d->input.fd, &stat) == -1) + return FALSE; + + if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length) + return FALSE; + + // file size changed; update memory map + skip = d->stream.next_frame - d->input.data; + + if (unmap_file(d->input.fdm, d->input.length) == -1) { + d->input.fdm = 0; + d->input.data = 0; + return FALSE; + } + + d->input.length = stat.st_size; + + d->input.fdm = map_file(d->input.fd, &d->input.length); + if (d->input.fdm == 0) { + d->input.data = 0; + return FALSE; + } + + d->input.data = (unsigned char *)d->input.fdm; + } + + mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip); + + } else +#endif + { + if (d->stream.next_frame) { + memmove(d->input.data, d->stream.next_frame, + d->input.length = &d->input.data[d->input.length] - d->stream.next_frame); + } + + do { + len = ::read(d->input.fd, d->input.data + d->input.length, MPEG_BUFFER_SIZE - d->input.length); + } + while (len == -1 && errno == EINTR); + + if (len == -1) { + qDebug("error reading audio"); + return FALSE; + } + else if (len == 0) { + d->input.eof = 1; + + assert(MPEG_BUFFER_SIZE - d->input.length >= MAD_BUFFER_GUARD); + + while (len < MAD_BUFFER_GUARD) + d->input.data[d->input.length + len++] = 0; + } + + mad_stream_buffer(&d->stream, d->input.data, d->input.length += len); + } + + return TRUE; +} + + +static mad_fixed_t left_err, right_err; +static const int bits = 16; +static const int shift = MAD_F_FRACBITS + 1 - bits; + + +inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error ) +{ + sample += error; + mad_fixed_t quantized = (sample >= MAD_F_ONE) ? MAD_F_ONE - 1 : ( (sample < -MAD_F_ONE) ? -MAD_F_ONE : sample ); + quantized &= ~((1L << shift) - 1); + error = sample - quantized; + return quantized >> shift; +} + + +inline void audio_pcm( short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right ) +{ + if ( right ) { + while (nsamples--) { + data[0] = audio_linear_dither( *left++, left_err ); + data[1] = audio_linear_dither( *right++, right_err ); + data += 2; + } + } else { + while (nsamples--) { + data[0] = data[1] = audio_linear_dither( *left++, left_err ); + data += 2; + } + } +} + + +bool LibMadPlugin::decode( short *output, long samples, long& samplesMade ) { + debugMsg( "LibMadPlugin::decode" ); + + static int buffered = 0; + static mad_fixed_t buffer[2][65536 * 2]; + int offset = buffered; + samplesMade = 0; + + static int maxBuffered = 8000; // 65536; + + if ( samples > maxBuffered ) + samples = maxBuffered; + + if ( d->flush ) { + buffered = 0; + offset = 0; + d->flush = FALSE; + } + + while ( buffered < maxBuffered ) { + + while (mad_frame_decode(&d->frame, &d->stream) == -1) { + if (!MAD_RECOVERABLE(d->stream.error)) { + debugMsg( "feed me" ); + return FALSE; // Feed me + } + if ( d->stream.error == MAD_ERROR_BADCRC ) { + mad_frame_mute(&d->frame); + qDebug( "error decoding, bad crc" ); + } + } + + mad_synth_frame(&d->synth, &d->frame); + int decodedSamples = d->synth.pcm.length; + memcpy( &(buffer[0][offset]), d->synth.pcm.samples[0], decodedSamples * sizeof(mad_fixed_t) ); + if ( d->synth.pcm.channels == 2 ) + memcpy( &(buffer[1][offset]), d->synth.pcm.samples[1], decodedSamples * sizeof(mad_fixed_t) ); + offset += decodedSamples; + buffered += decodedSamples; + } + + audio_pcm( output, samples, buffer[0], (d->synth.pcm.channels == 2) ? buffer[1] : 0 ); +// audio_pcm( output, samples, buffer[1], buffer[0] ); +// audio_pcm( output, samples, buffer[0], buffer[1] ); + samplesMade = samples; + memmove( buffer[0], &(buffer[0][samples]), (buffered - samples) * sizeof(mad_fixed_t) ); + if ( d->synth.pcm.channels == 2 ) + memmove( buffer[1], &(buffer[1][samples]), (buffered - samples) * sizeof(mad_fixed_t) ); + buffered -= samples; + + return TRUE; +} + +/* +bool LibMadPlugin::audioReadMonoSamples( short *, long, long&, int ) { + debugMsg( "LibMadPlugin::audioReadMonoSamples" ); + return FALSE; +} + + +bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) { +*/ +bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) { + debugMsg( "LibMadPlugin::audioReadStereoSamples" ); + + static bool needInput = TRUE; + + if ( samples == 0 ) + return TRUE; + + do { + if ( needInput ) + if ( !read() ) { +// if ( d->input.eof ) +// needInput = FALSE; +// else + return TRUE; + } + + needInput = FALSE; + + if ( decode( output, samples, samplesMade ) ) + return FALSE; + else + needInput = TRUE; + } + while ( ( samplesMade < samples ) && ( !d->input.eof ) ); +/* + static bool firstTimeThru = TRUE; + + if ( firstTimeThru ) { + firstTimeThru = FALSE; + decode( output, samples, samplesMade ); + return FALSE; + } else +*/ + return TRUE; +} + + +double LibMadPlugin::getTime() { + debugMsg( "LibMadPlugin::getTime" ); + return 0.0; +} + + +void LibMadPlugin::printID3Tags() { + debugMsg( "LibMadPlugin::printID3Tags" ); + + char id3v1[128 + 1]; + + if ( ::lseek( d->input.fd, -128, SEEK_END ) == -1 ) { + qDebug( "error seeking to id3 tags" ); + return; + } + + if ( ::read( d->input.fd, id3v1, 128 ) != 128 ) { + qDebug( "error reading in id3 tags" ); + return; + } + + if ( ::strncmp( (const char *)id3v1, "TAG", 3 ) != 0 ) { + debugMsg( "sorry, no id3 tags" ); + } else { + int len[5] = { 30, 30, 30, 4, 30 }; + QString label[5] = { tr( "Title" ), tr( "Artist" ), tr( "Album" ), tr( "Year" ), tr( "Comment" ) }; + char *ptr = id3v1 + 3, *ptr2 = ptr + len[0]; + qDebug( "ID3 tags in file:" ); + info = ""; + for ( int i = 0; i < 5; ptr += len[i], i++, ptr2 += len[i] ) { + char push = *ptr2; + *ptr2 = '\0'; + char *ptr3 = ptr2; + while ( ptr3-1 >= ptr && isspace(ptr3[-1]) ) ptr3--; + char push2 = *ptr3; *ptr3 = '\0'; + if ( strcmp( ptr, "" ) ) + info += ( i != 0 ? ", " : "" ) + label[i] + ": " + ptr; + //qDebug( info.latin1() ); + *ptr3 = push2; + *ptr2 = push; + } + if (id3v1[126] == 0 && id3v1[127] != 0) + info += tr( ", Track: " ) + id3v1[127]; + } + + if ( ::lseek(d->input.fd, 0, SEEK_SET) == -1 ) { + qDebug( "error seeking back to beginning" ); + return; + } +} + diff --git a/core/multimedia/opieplayer/libmad/libmadplugin.h b/core/multimedia/opieplayer/libmad/libmadplugin.h new file mode 100644 index 0000000..88647ae --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/libmadplugin.h @@ -0,0 +1,101 @@ +/********************************************************************** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef LIBMAD_PLUGIN_H +#define LIBMAD_PLUGIN_H + + +#include +#include "mediaplayerplugininterface.h" + + +class LibMadPluginData; + + +class LibMadPlugin : public MediaPlayerDecoder { + +public: + LibMadPlugin(); + ~LibMadPlugin(); + + const char *pluginName() { return "LibMadPlugin"; } + const char *pluginComment() { return "This is the libmad library that has been wrapped as a plugin"; } + double pluginVersion() { return 1.0; } + + bool isFileSupported( const QString& ); + bool open( const QString& ); + bool close(); + bool isOpen(); + const QString &fileInfo() { return info; } + + // If decoder doesn't support audio then return 0 here + int audioStreams(); + int audioChannels( int stream ); + int audioFrequency( int stream ); + int audioSamples( int stream ); + bool audioSetSample( long sample, int stream ); + long audioGetSample( int stream ); +// bool audioReadMonoSamples( short *output, long samples, long& samplesRead, int stream ); +// bool audioReadStereoSamples( short *output, long samples, long& samplesRead, int stream ); + bool audioReadSamples( short *output, int channels, long samples, long& samplesRead, int stream ); +// bool audioReadSamples( short *output, int channel, long samples, int stream ); +// bool audioReReadSamples( short *output, int channel, long samples, int stream ); + + + bool read(); + bool decode( short *output, long samples, long& samplesRead ); + void printID3Tags(); + + + // If decoder doesn't support video then return 0 here + int videoStreams() { return 0; } + int videoWidth( int ) { return 0; } + int videoHeight( int ) { return 0; } + double videoFrameRate( int ) { return 0.0; } + int videoFrames( int ) { return 0; } + bool videoSetFrame( long, int ) { return FALSE; } + long videoGetFrame( int ) { return 0; } + bool videoReadFrame( unsigned char **, int, int, int, int, ColorFormat, int ) { return FALSE; } + bool videoReadScaledFrame( unsigned char **, int, int, int, int, int, int, ColorFormat, int ) { return FALSE; } + bool videoReadYUVFrame( char *, char *, char *, int, int, int, int, int ) { return FALSE; } + + // Profiling + double getTime(); + + // Ignore if these aren't supported + bool setSMP( int ) { return FALSE; } + bool setMMX( bool ) { return FALSE; } + + // Capabilities + bool supportsAudio() { return TRUE; } + bool supportsVideo() { return FALSE; } + bool supportsYUV() { return FALSE; } + bool supportsMMX() { return TRUE; } + bool supportsSMP() { return FALSE; } + bool supportsStereo() { return TRUE; } + bool supportsScaling() { return FALSE; } + +private: + LibMadPluginData *d; + QString info; + +}; + + +#endif diff --git a/core/multimedia/opieplayer/libmad/libmadpluginimpl.cpp b/core/multimedia/opieplayer/libmad/libmadpluginimpl.cpp new file mode 100644 index 0000000..028c658 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/libmadpluginimpl.cpp @@ -0,0 +1,70 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "libmadplugin.h" +#include "libmadpluginimpl.h" + + +LibMadPluginImpl::LibMadPluginImpl() + : libmadplugin(0), ref(0) +{ +} + + +LibMadPluginImpl::~LibMadPluginImpl() +{ + if ( libmadplugin ) + delete libmadplugin; +} + + +MediaPlayerDecoder *LibMadPluginImpl::decoder() +{ + if ( !libmadplugin ) + libmadplugin = new LibMadPlugin; + return libmadplugin; +} + + +MediaPlayerEncoder *LibMadPluginImpl::encoder() +{ + return NULL; +} + + +#ifndef QT_NO_COMPONENT + + +QRESULT LibMadPluginImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ + *iface = 0; + if ( ( uuid == IID_QUnknown ) || ( uuid == IID_MediaPlayerPlugin ) ) + *iface = this, (*iface)->addRef(); + return QS_OK; +} + + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( LibMadPluginImpl ) +} + + +#endif + diff --git a/core/multimedia/opieplayer/libmad/libmadpluginimpl.h b/core/multimedia/opieplayer/libmad/libmadpluginimpl.h new file mode 100644 index 0000000..a26b421 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/libmadpluginimpl.h @@ -0,0 +1,53 @@ +/********************************************************************** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef LIBMAD_PLUGIN_IMPL_H +#define LIBMAD_PLUGIN_IMPL_H + + +#include "../mediaplayerplugininterface.h" + + +class LibMadPlugin; + + +class LibMadPluginImpl : public MediaPlayerPluginInterface +{ +public: + LibMadPluginImpl(); + virtual ~LibMadPluginImpl(); + +#ifndef QT_NO_COMPONENT + + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT + +#endif + + virtual MediaPlayerDecoder *decoder(); + virtual MediaPlayerEncoder *encoder(); + +private: + LibMadPlugin *libmadplugin; + ulong ref; +}; + + +#endif + diff --git a/core/multimedia/opieplayer/libmad/mad.h b/core/multimedia/opieplayer/libmad/mad.h new file mode 100644 index 0000000..9db9da3 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/mad.h @@ -0,0 +1,830 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * If you would like to negotiate alternate licensing terms, you may do + * so by contacting the author: Robert Leslie + */ + +# define SIZEOF_INT 4 +# define SIZEOF_LONG 4 +# define SIZEOF_LONG_LONG 8 + +/* Id: version.h,v 1.16 2001/04/05 04:57:11 rob Exp */ + +# ifndef LIBMAD_VERSION_H +# define LIBMAD_VERSION_H + +# define MAD_VERSION_MAJOR 0 +# define MAD_VERSION_MINOR 13 +# define MAD_VERSION_PATCH 0 +# define MAD_VERSION_EXTRA " (beta)" + +# define MAD_VERSION_STRINGIZE(str) #str +# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num) + +# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) "." \ + MAD_VERSION_STRING(MAD_VERSION_MINOR) "." \ + MAD_VERSION_STRING(MAD_VERSION_PATCH) \ + MAD_VERSION_EXTRA + +# define MAD_PUBLISHYEAR "2000-2001" +# define MAD_AUTHOR "Robert Leslie" +# define MAD_EMAIL "rob@mars.org" + +extern char const mad_version[]; +extern char const mad_copyright[]; +extern char const mad_author[]; +extern char const mad_build[]; + +# endif + +/* Id: fixed.h,v 1.23 2001/04/05 04:57:11 rob Exp */ + +# ifndef LIBMAD_FIXED_H +# define LIBMAD_FIXED_H + +# if SIZEOF_INT >= 4 +typedef signed int mad_fixed_t; + +typedef signed int mad_fixed64hi_t; +typedef unsigned int mad_fixed64lo_t; +# else +typedef signed long mad_fixed_t; + +typedef signed long mad_fixed64hi_t; +typedef unsigned long mad_fixed64lo_t; +# endif + +/* + * Fixed-point format: 0xABBBBBBB + * A == whole part (sign + 3 bits) + * B == fractional part (28 bits) + * + * Values are signed two's complement, so the effective range is: + * 0x80000000 to 0x7fffffff + * -8.0 to +7.9999999962747097015380859375 + * + * The smallest representable value is: + * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9) + * + * 28 bits of fractional accuracy represent about + * 8.6 digits of decimal accuracy. + * + * Fixed-point numbers can be added or subtracted as normal + * integers, but multiplication requires shifting the 64-bit result + * from 56 fractional bits back to 28 (and rounding.) + * + * Changing the definition of MAD_F_FRACBITS is only partially + * supported, and must be done with care. + */ + +# define MAD_F_FRACBITS 28 + +# if MAD_F_FRACBITS == 28 +# define MAD_F(x) ((mad_fixed_t) (x##L)) +# else +# if MAD_F_FRACBITS < 28 +# warning "MAD_F_FRACBITS < 28" +# define MAD_F(x) ((mad_fixed_t) \ + (((x##L) + \ + (1L << (28 - MAD_F_FRACBITS - 1))) >> \ + (28 - MAD_F_FRACBITS))) +# elif MAD_F_FRACBITS > 28 +# error "MAD_F_FRACBITS > 28 not currently supported" +# define MAD_F(x) ((mad_fixed_t) \ + ((x##L) << (MAD_F_FRACBITS - 28))) +# endif +# endif + +# define MAD_F_MIN ((mad_fixed_t) -0x80000000L) +# define MAD_F_MAX ((mad_fixed_t) +0x7fffffffL) + +# define MAD_F_ONE MAD_F(0x10000000) + +# define mad_f_tofixed(x) ((mad_fixed_t) \ + ((x) * (double) (1L << MAD_F_FRACBITS) + 0.5)) +# define mad_f_todouble(x) ((double) \ + ((x) / (double) (1L << MAD_F_FRACBITS))) + +# define mad_f_intpart(x) ((x) >> MAD_F_FRACBITS) +# define mad_f_fracpart(x) ((x) & ((1L << MAD_F_FRACBITS) - 1)) + /* (x should be positive) */ + +# define mad_f_fromint(x) ((x) << MAD_F_FRACBITS) + +# define mad_f_add(x, y) ((x) + (y)) +# define mad_f_sub(x, y) ((x) - (y)) + +# if defined(FPM_64BIT) + +/* + * This version should be the most accurate if 64-bit (long long) types are + * supported by the compiler, although it may not be the most efficient. + */ +# if defined(OPT_ACCURACY) +# define mad_f_mul(x, y) \ + ((mad_fixed_t) \ + ((((signed long long) (x) * (y)) + \ + (1L << (MAD_F_SCALEBITS - 1))) >> MAD_F_SCALEBITS)) +# else +# define mad_f_mul(x, y) \ + ((mad_fixed_t) (((signed long long) (x) * (y)) >> MAD_F_SCALEBITS)) +# endif + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- Intel --------------------------------------------------------------- */ + +# elif defined(FPM_INTEL) + +/* + * This Intel version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("imull %3" \ + : "=a" (lo), "=d" (hi) \ + : "%a" (x), "rm" (y) \ + : "cc") + +# if defined(OPT_ACCURACY) +/* + * This gives best accuracy but is not very fast. + */ +# define MAD_F_MLA(hi, lo, x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + asm ("addl %2,%0\n\t" \ + "adcl %3,%1" \ + : "=rm" (lo), "=rm" (hi) \ + : "r" (__lo), "r" (__hi), "0" (lo), "1" (hi) \ + : "cc"); \ + }) +# endif /* OPT_ACCURACY */ + +# if defined(OPT_ACCURACY) +/* + * Surprisingly, this is faster than SHRD followed by ADC. + */ +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed64hi_t __hi_; \ + mad_fixed64lo_t __lo_; \ + mad_fixed_t __result; \ + asm ("addl %4,%2\n\t" \ + "adcl %5,%3" \ + : "=rm" (__lo_), "=rm" (__hi_) \ + : "0" (lo), "1" (hi), \ + "ir" (1L << (MAD_F_SCALEBITS - 1)), "ir" (0) \ + : "cc"); \ + asm ("shrdl %3,%2,%1" \ + : "=rm" (__result) \ + : "0" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# else +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("shrdl %3,%2,%1" \ + : "=rm" (__result) \ + : "0" (lo), "r" (hi), "I" (MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# endif /* OPT_ACCURACY */ + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- ARM ----------------------------------------------------------------- */ + +# elif defined(FPM_ARM) + +/* + * This ARM V4 version is as accurate as FPM_64BIT but much faster. The + * least significant bit is properly rounded at no CPU cycle cost! + */ +# if 1 +/* + * There's a bug somewhere, possibly in the compiler, that sometimes makes + * this necessary instead of the default implementation via MAD_F_MLX and + * mad_f_scale64. It may be related to the use (or lack) of + * -finline-functions and/or -fstrength-reduce. + * + * This is also apparently faster than MAD_F_MLX/mad_f_scale64. + */ +# define mad_f_mul(x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + mad_fixed_t __result; \ + asm ("smull %0, %1, %3, %4\n\t" \ + "movs %0, %0, lsr %5\n\t" \ + "adc %2, %0, %1, lsl %6" \ + : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \ + : "%r" (x), "r" (y), \ + "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# endif + +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("smull %0, %1, %2, %3" \ + : "=&r" (lo), "=&r" (hi) \ + : "%r" (x), "r" (y)) + +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("smlal %0, %1, %2, %3" \ + : "+r" (lo), "+r" (hi) \ + : "%r" (x), "r" (y)) + +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("movs %0, %1, lsr %3\n\t" \ + "adc %0, %0, %2, lsl %4" \ + : "=r" (__result) \ + : "r" (lo), "r" (hi), \ + "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- MIPS ---------------------------------------------------------------- */ + +# elif defined(FPM_MIPS) + +/* + * This MIPS version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("mult %2,%3" \ + : "=l" (lo), "=h" (hi) \ + : "%r" (x), "r" (y)) + +# if defined(HAVE_MADD_ASM) +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("madd %2,%3" \ + : "+l" (lo), "+h" (hi) \ + : "%r" (x), "r" (y)) +# elif defined(HAVE_MADD16_ASM) +/* + * This loses significant accuracy due to the 16-bit integer limit in the + * multiply/accumulate instruction. + */ +# define MAD_F_ML0(hi, lo, x, y) \ + asm ("mult %2,%3" \ + : "=l" (lo), "=h" (hi) \ + : "%r" ((x) >> 12), "r" ((y) >> 16)) +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("madd16 %2,%3" \ + : "+l" (lo), "+h" (hi) \ + : "%r" ((x) >> 12), "r" ((y) >> 16)) +# define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo)) +# endif + +# if defined(OPT_SPEED) +# define mad_f_scale64(hi, lo) \ + ((mad_fixed_t) ((hi) << (32 - MAD_F_SCALEBITS))) +# define MAD_F_SCALEBITS MAD_F_FRACBITS +# endif + +/* --- SPARC --------------------------------------------------------------- */ + +# elif defined(FPM_SPARC) + +/* + * This SPARC V8 version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("smul %2, %3, %0\n\t" \ + "rd %%y, %1" \ + : "=r" (lo), "=r" (hi) \ + : "%r" (x), "rI" (y)) + +/* --- PowerPC ------------------------------------------------------------- */ + +# elif defined(FPM_PPC) + +/* + * This PowerPC version is tuned for the 4xx embedded processors. It is + * effectively a tuned version of FPM_64BIT. It is a little faster and just + * as accurate. The disposition of the least significant bit depends on + * OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("mulhw %1, %2, %3\n\t" \ + "mullw %0, %2, %3" \ + : "=&r" (lo), "=&r" (hi) \ + : "%r" (x), "r" (y)) + +# define MAD_F_MLA(hi, lo, x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + asm ("addc %0, %2, %3\n\t" \ + "adde %1, %4, %5" \ + : "=r" (lo), "=r" (hi) \ + : "%r" (__lo), "0" (lo), "%r" (__hi), "1" (hi)); \ + }) + +# if defined(OPT_ACCURACY) +/* + * This is accurate and ~2 - 2.5 times slower than the unrounded version. + * + * The __volatile__ improves the generated code by another 5% (fewer spills + * to memory); eventually they should be removed. + */ +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + mad_fixed64hi_t __hi_; \ + mad_fixed64lo_t __lo_; \ + asm __volatile__ ("addc %0, %2, %4\n\t" \ + "addze %1, %3" \ + : "=r" (__lo_), "=r" (__hi_) \ + : "r" (lo), "r" (hi), "r" (1 << (MAD_F_SCALEBITS - 1))); \ + asm __volatile__ ("rlwinm %0, %2,32-%3,0,%3-1\n\t" \ + "rlwimi %0, %1,32-%3,%3,31" \ + : "=&r" (__result) \ + : "r" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS)); \ + __result; \ + }) +# else +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("rlwinm %0, %2,32-%3,0,%3-1\n\t" \ + "rlwimi %0, %1,32-%3,%3,31" \ + : "=r" (__result) \ + : "r" (lo), "r" (hi), "I" (MAD_F_SCALEBITS)); \ + __result; \ + }) +# endif /* OPT_ACCURACY */ + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- Default ------------------------------------------------------------- */ + +# elif defined(FPM_DEFAULT) + +/* + * This version is the most portable but it loses significant accuracy. + * Furthermore, accuracy is biased against the second argument, so care + * should be taken when ordering operands. + * + * The scale factors are constant as this is not used with SSO. + * + * Pre-rounding is required to stay within the limits of compliance. + */ +# define mad_f_mul(x, y) ((((x) + (1L << 11)) >> 12) * \ + (((y) + (1L << 15)) >> 16)) + +/* ------------------------------------------------------------------------- */ + +# else +# error "no FPM selected" +# endif + +/* default implementations */ + +# if !defined(mad_f_mul) +# define mad_f_mul(x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + mad_f_scale64(__hi, __lo); \ + }) +# endif + +# if !defined(MAD_F_MLA) +# define MAD_F_ML0(hi, lo, x, y) ((lo) = mad_f_mul((x), (y))) +# define MAD_F_MLA(hi, lo, x, y) ((lo) += mad_f_mul((x), (y))) +# define MAD_F_MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) +# endif + +# if !defined(MAD_F_ML0) +# define MAD_F_ML0(hi, lo, x, y) MAD_F_MLX((hi), (lo), (x), (y)) +# endif + +# if !defined(MAD_F_MLZ) +# define MAD_F_MLZ(hi, lo) mad_f_scale64((hi), (lo)) +# endif + +# if !defined(mad_f_scale64) +# if defined(OPT_ACCURACY) +# define mad_f_scale64(hi, lo) \ + ((((mad_fixed_t) \ + (((hi) << (32 - (MAD_F_SCALEBITS - 1))) | \ + ((lo) >> (MAD_F_SCALEBITS - 1)))) + 1) >> 1) +# else +# define mad_f_scale64(hi, lo) \ + ((mad_fixed_t) \ + (((hi) << (32 - MAD_F_SCALEBITS)) | \ + ((lo) >> MAD_F_SCALEBITS))) +# endif +# define MAD_F_SCALEBITS MAD_F_FRACBITS +# endif + +/* miscellaneous C routines */ + +mad_fixed_t mad_f_abs(mad_fixed_t); + +# endif + +/* Id: bit.h,v 1.7 2001/04/05 04:57:11 rob Exp */ + +# ifndef LIBMAD_BIT_H +# define LIBMAD_BIT_H + +struct mad_bitptr { + unsigned char const *byte; + unsigned short cache; + unsigned short left; +}; + +void mad_bit_init(struct mad_bitptr *, unsigned char const *); + +# define mad_bit_finish(bitptr) /* nothing */ + +unsigned int mad_bit_length(struct mad_bitptr const *, + struct mad_bitptr const *); + +# define mad_bit_bitsleft(bitptr) ((bitptr)->left) +unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *); + +void mad_bit_skip(struct mad_bitptr *, unsigned int); +unsigned long mad_bit_read(struct mad_bitptr *, unsigned int); +void mad_bit_write(struct mad_bitptr *, unsigned int, unsigned long); + +unsigned short mad_bit_crc(struct mad_bitptr, unsigned int, unsigned short); + +# endif + +/* Id: timer.h,v 1.10 2001/04/05 04:57:11 rob Exp */ + +# ifndef LIBMAD_TIMER_H +# define LIBMAD_TIMER_H + +typedef struct { + signed long seconds; /* whole seconds */ + unsigned long fraction; /* 1/MAD_TIMER_RESOLUTION seconds */ +} mad_timer_t; + +extern mad_timer_t const mad_timer_zero; + +# define MAD_TIMER_RESOLUTION 352800000UL + +enum mad_units { + MAD_UNITS_HOURS = -2, + MAD_UNITS_MINUTES = -1, + MAD_UNITS_SECONDS = 0, + + /* metric units */ + + MAD_UNITS_DECISECONDS = 10, + MAD_UNITS_CENTISECONDS = 100, + MAD_UNITS_MILLISECONDS = 1000, + + /* audio sample units */ + + MAD_UNITS_8000_HZ = 8000, + MAD_UNITS_11025_HZ = 11025, + MAD_UNITS_12000_HZ = 12000, + + MAD_UNITS_16000_HZ = 16000, + MAD_UNITS_22050_HZ = 22050, + MAD_UNITS_24000_HZ = 24000, + + MAD_UNITS_32000_HZ = 32000, + MAD_UNITS_44100_HZ = 44100, + MAD_UNITS_48000_HZ = 48000, + + /* video frame/field units */ + + MAD_UNITS_24_FPS = 24, + MAD_UNITS_25_FPS = 25, + MAD_UNITS_30_FPS = 30, + MAD_UNITS_48_FPS = 48, + MAD_UNITS_50_FPS = 50, + MAD_UNITS_60_FPS = 60, + + /* CD audio frames */ + + MAD_UNITS_75_FPS = 75, + + /* video drop-frame units */ + + MAD_UNITS_23_976_FPS = -24, + MAD_UNITS_24_975_FPS = -25, + MAD_UNITS_29_97_FPS = -30, + MAD_UNITS_47_952_FPS = -48, + MAD_UNITS_49_95_FPS = -50, + MAD_UNITS_59_94_FPS = -60 +}; + +# define mad_timer_reset(timer) (*(timer) = mad_timer_zero) + +int mad_timer_compare(mad_timer_t, mad_timer_t); + +# define mad_timer_sign(timer) mad_timer_compare((timer), mad_timer_zero) + +void mad_timer_negate(mad_timer_t *); +mad_timer_t mad_timer_abs(mad_timer_t); + +void mad_timer_set(mad_timer_t *, unsigned long, unsigned long, unsigned long); +void mad_timer_add(mad_timer_t *, mad_timer_t); +void mad_timer_multiply(mad_timer_t *, signed long); + +signed long mad_timer_count(mad_timer_t, enum mad_units); +unsigned long mad_timer_fraction(mad_timer_t, unsigned long); +void mad_timer_string(mad_timer_t, char *, char const *, + enum mad_units, enum mad_units, unsigned long); + +# endif + +/* Id: stream.h,v 1.12 2001/04/10 05:18:21 rob Exp */ + +# ifndef LIBMAD_STREAM_H +# define LIBMAD_STREAM_H + +# define MAD_BUFFER_GUARD 8 +# define MAD_BUFFER_MDLEN (511 + 2048 + MAD_BUFFER_GUARD) + +enum mad_error { + MAD_ERROR_BUFLEN = 0x0001, /* input buffer too small (or EOF) */ + MAD_ERROR_BUFPTR = 0x0002, /* invalid (null) buffer pointer */ + + MAD_ERROR_NOMEM = 0x0031, /* not enough memory */ + + MAD_ERROR_LOSTSYNC = 0x0101, /* lost synchronization */ + MAD_ERROR_BADLAYER = 0x0102, /* reserved header layer value */ + MAD_ERROR_BADBITRATE = 0x0103, /* forbidden bitrate value */ + MAD_ERROR_BADSAMPLERATE = 0x0104, /* reserved sample frequency value */ + MAD_ERROR_BADEMPHASIS = 0x0105, /* reserved emphasis value */ + + MAD_ERROR_BADCRC = 0x0201, /* CRC check failed */ + MAD_ERROR_BADBITALLOC = 0x0211, /* forbidden bit allocation value */ + MAD_ERROR_BADSCALEFACTOR = 0x0221, /* bad scalefactor index */ + MAD_ERROR_BADFRAMELEN = 0x0231, /* bad frame length */ + MAD_ERROR_BADBIGVALUES = 0x0232, /* bad big_values count */ + MAD_ERROR_BADBLOCKTYPE = 0x0233, /* reserved block_type */ + MAD_ERROR_BADSCFSI = 0x0234, /* bad scalefactor selection info */ + MAD_ERROR_BADDATAPTR = 0x0235, /* bad main_data_begin pointer */ + MAD_ERROR_BADPART3LEN = 0x0236, /* bad audio data length */ + MAD_ERROR_BADHUFFTABLE = 0x0237, /* bad Huffman table select */ + MAD_ERROR_BADHUFFDATA = 0x0238, /* Huffman data overrun */ + MAD_ERROR_BADSTEREO = 0x0239 /* incompatible block_type for JS */ +}; + +# define MAD_RECOVERABLE(error) ((error) & 0xff00) + +struct mad_stream { + unsigned char const *buffer; /* input bitstream buffer */ + unsigned char const *bufend; /* end of buffer */ + unsigned long skiplen; /* bytes to skip before next frame */ + + int sync; /* stream sync found */ + unsigned long freerate; /* free bitrate (fixed) */ + + unsigned char const *this_frame; /* start of current frame */ + unsigned char const *next_frame; /* start of next frame */ + struct mad_bitptr ptr; /* current processing bit pointer */ + + struct mad_bitptr anc_ptr; /* ancillary bits pointer */ + unsigned int anc_bitlen; /* number of ancillary bits */ + + unsigned char (*main_data)[MAD_BUFFER_MDLEN]; + /* Layer III main_data() */ + unsigned int md_len; /* bytes in main_data */ + + int options; /* decoding options (see below) */ + enum mad_error error; /* error code (see above) */ +}; + +enum { + MAD_OPTION_IGNORECRC = 0x0001, /* ignore CRC errors */ + MAD_OPTION_HALFSAMPLERATE = 0x0002, /* generate PCM at 1/2 sample rate */ +# if 0 /* not yet implemented */ + MAD_OPTION_LEFTCHANNEL = 0x0010, /* decode left channel only */ + MAD_OPTION_RIGHTCHANNEL = 0x0020, /* decode right channel only */ + MAD_OPTION_SINGLECHANNEL = 0x0030, /* combine channels */ +# endif +}; + +void mad_stream_init(struct mad_stream *); +void mad_stream_finish(struct mad_stream *); + +# define mad_stream_options(stream, opts) ((stream)->options = (opts)) + +void mad_stream_buffer(struct mad_stream *, + unsigned char const *, unsigned long); +void mad_stream_skip(struct mad_stream *, unsigned long); + +int mad_stream_sync(struct mad_stream *); + +# endif + +/* Id: frame.h,v 1.13 2001/04/05 04:57:11 rob Exp */ + +# ifndef LIBMAD_FRAME_H +# define LIBMAD_FRAME_H + +enum mad_layer { + MAD_LAYER_I = 1, /* Layer I */ + MAD_LAYER_II = 2, /* Layer II */ + MAD_LAYER_III = 3 /* Layer III */ +}; + +enum mad_mode { + MAD_MODE_SINGLE_CHANNEL = 0, /* single channel */ + MAD_MODE_DUAL_CHANNEL = 1, /* dual channel */ + MAD_MODE_JOINT_STEREO = 2, /* joint (MS/intensity) stereo */ + MAD_MODE_STEREO = 3 /* normal LR stereo */ +}; + +enum mad_emphasis { + MAD_EMPHASIS_NONE = 0, /* no emphasis */ + MAD_EMPHASIS_50_15_US = 1, /* 50/15 microseconds emphasis */ + MAD_EMPHASIS_CCITT_J_17 = 3 /* CCITT J.17 emphasis */ +}; + +struct mad_frame { + struct mad_header { + enum mad_layer layer; /* audio layer (1, 2, or 3) */ + enum mad_mode mode; /* channel mode (see above) */ + int mode_extension; /* additional mode info */ + enum mad_emphasis emphasis; /* de-emphasis to use (see above) */ + + unsigned long bitrate; /* stream bitrate (bps) */ + unsigned int samplerate; /* sampling frequency (Hz) */ + + unsigned short crc_check; /* frame CRC accumulator */ + unsigned short crc_target; /* final target CRC checksum */ + + int flags; /* flags (see below) */ + int private_bits; /* private bits (see below) */ + + mad_timer_t duration; /* audio playing time of frame */ + } header; + + int options; /* decoding options (from stream) */ + + mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */ + mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */ +}; + +# define MAD_NCHANNELS(header) ((header)->mode ? 2 : 1) +# define MAD_NSBSAMPLES(header) \ + ((header)->layer == MAD_LAYER_I ? 12 : \ + (((header)->layer == MAD_LAYER_III && \ + ((header)->flags & MAD_FLAG_LSF_EXT)) ? 18 : 36)) + +enum { + MAD_FLAG_NPRIVATE_III = 0x0007, /* number of Layer III private bits */ + MAD_FLAG_INCOMPLETE = 0x0008, /* header but not data is decoded */ + + MAD_FLAG_PROTECTION = 0x0010, /* frame has CRC protection */ + MAD_FLAG_COPYRIGHT = 0x0020, /* frame is copyright */ + MAD_FLAG_ORIGINAL = 0x0040, /* frame is original (else copy) */ + MAD_FLAG_PADDING = 0x0080, /* frame has additional slot */ + + MAD_FLAG_I_STEREO = 0x0100, /* uses intensity joint stereo */ + MAD_FLAG_MS_STEREO = 0x0200, /* uses middle/side joint stereo */ + MAD_FLAG_FREEFORMAT = 0x0400, /* uses free format bitrate */ + + MAD_FLAG_LSF_EXT = 0x1000, /* lower sampling freq. extension */ + MAD_FLAG_MC_EXT = 0x2000, /* multichannel audio extension */ + MAD_FLAG_MPEG_2_5_EXT = 0x4000 /* MPEG 2.5 (unofficial) extension */ +}; + +enum { + MAD_PRIVATE_HEADER = 0x0100, /* header private bit */ + MAD_PRIVATE_III = 0x001f /* Layer III private bits (up to 5) */ +}; + +void mad_header_init(struct mad_header *); + +# define mad_header_finish(header) /* nothing */ + +int mad_header_decode(struct mad_header *, struct mad_stream *); + +void mad_frame_init(struct mad_frame *); +void mad_frame_finish(struct mad_frame *); + +int mad_frame_decode(struct mad_frame *, struct mad_stream *); + +void mad_frame_mute(struct mad_frame *); + +# endif + +/* Id: synth.h,v 1.8 2001/04/05 04:57:11 rob Exp */ + +# ifndef LIBMAD_SYNTH_H +# define LIBMAD_SYNTH_H + +struct mad_synth { + mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */ + /* [ch][eo][peo][s][v] */ + + unsigned int phase; /* current processing phase */ + + struct mad_pcm { + unsigned int samplerate; /* sampling frequency (Hz) */ + unsigned short channels; /* number of channels */ + unsigned short length; /* number of samples per channel */ + mad_fixed_t samples[2][1152]; /* PCM output samples */ + } pcm; +}; + +void mad_synth_init(struct mad_synth *); + +# define mad_synth_finish(synth) /* nothing */ + +void mad_synth_mute(struct mad_synth *); + +void mad_synth_frame(struct mad_synth *, struct mad_frame const *); + +# endif + +/* Id: decoder.h,v 1.9 2001/04/05 04:57:11 rob Exp */ + +# ifndef LIBMAD_DECODER_H +# define LIBMAD_DECODER_H + +enum mad_decoder_mode { + MAD_DECODER_MODE_SYNC = 0, + MAD_DECODER_MODE_ASYNC +}; + +enum mad_flow { + MAD_FLOW_CONTINUE = 0x0000, + MAD_FLOW_STOP = 0x0010, + MAD_FLOW_BREAK = 0x0011, + MAD_FLOW_IGNORE = 0x0020 +}; + +struct mad_decoder { + enum mad_decoder_mode mode; + + int options; + + struct { + long pid; + int in; + int out; + } async; + + struct { + struct mad_stream stream; + struct mad_frame frame; + struct mad_synth synth; + } *sync; + + void *cb_data; + + enum mad_flow (*input_func)(void *, struct mad_stream *); + enum mad_flow (*header_func)(void *, struct mad_header const *); + enum mad_flow (*filter_func)(void *, struct mad_frame *); + enum mad_flow (*output_func)(void *, + struct mad_header const *, struct mad_pcm *); + enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); + enum mad_flow (*message_func)(void *, void *, unsigned int *); +}; + +void mad_decoder_init(struct mad_decoder *, void *, + enum mad_flow (*)(void *, struct mad_stream *), + enum mad_flow (*)(void *, struct mad_header const *), + enum mad_flow (*)(void *, struct mad_frame *), + enum mad_flow (*)(void *, + struct mad_header const *, + struct mad_pcm *), + enum mad_flow (*)(void *, + struct mad_stream *, + struct mad_frame *), + enum mad_flow (*)(void *, void *, unsigned int *)); +int mad_decoder_finish(struct mad_decoder *); + +# define mad_decoder_options(decoder, opts) ((decoder)->options = (opts)) + +int mad_decoder_run(struct mad_decoder *, enum mad_decoder_mode); +int mad_decoder_message(struct mad_decoder *, void *, unsigned int *); + +# endif + diff --git a/core/multimedia/opieplayer/libmad/qc_table.dat b/core/multimedia/opieplayer/libmad/qc_table.dat new file mode 100644 index 0000000..92b7f38 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/qc_table.dat @@ -0,0 +1,77 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +/* + * These are the Layer II classes of quantization. + * The table is derived from Table B.4 of ISO/IEC 11172-3. + */ + + { 3, 2, 5, + MAD_F(0x15555555) /* 1.33333333333 => 1.33333333209, e 0.00000000124 */, + MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ }, + { 5, 3, 7, + MAD_F(0x1999999a) /* 1.60000000000 => 1.60000000149, e -0.00000000149 */, + MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ }, + { 7, 0, 3, + MAD_F(0x12492492) /* 1.14285714286 => 1.14285714179, e 0.00000000107 */, + MAD_F(0x04000000) /* 0.25000000000 => 0.25000000000, e 0.00000000000 */ }, + { 9, 4, 10, + MAD_F(0x1c71c71c) /* 1.77777777777 => 1.77777777612, e 0.00000000165 */, + MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ }, + { 15, 0, 4, + MAD_F(0x11111111) /* 1.06666666666 => 1.06666666642, e 0.00000000024 */, + MAD_F(0x02000000) /* 0.12500000000 => 0.12500000000, e 0.00000000000 */ }, + { 31, 0, 5, + MAD_F(0x10842108) /* 1.03225806452 => 1.03225806355, e 0.00000000097 */, + MAD_F(0x01000000) /* 0.06250000000 => 0.06250000000, e 0.00000000000 */ }, + { 63, 0, 6, + MAD_F(0x10410410) /* 1.01587301587 => 1.01587301493, e 0.00000000094 */, + MAD_F(0x00800000) /* 0.03125000000 => 0.03125000000, e 0.00000000000 */ }, + { 127, 0, 7, + MAD_F(0x10204081) /* 1.00787401575 => 1.00787401572, e 0.00000000003 */, + MAD_F(0x00400000) /* 0.01562500000 => 0.01562500000, e 0.00000000000 */ }, + { 255, 0, 8, + MAD_F(0x10101010) /* 1.00392156863 => 1.00392156839, e 0.00000000024 */, + MAD_F(0x00200000) /* 0.00781250000 => 0.00781250000, e 0.00000000000 */ }, + { 511, 0, 9, + MAD_F(0x10080402) /* 1.00195694716 => 1.00195694715, e 0.00000000001 */, + MAD_F(0x00100000) /* 0.00390625000 => 0.00390625000, e 0.00000000000 */ }, + { 1023, 0, 10, + MAD_F(0x10040100) /* 1.00097751711 => 1.00097751617, e 0.00000000094 */, + MAD_F(0x00080000) /* 0.00195312500 => 0.00195312500, e 0.00000000000 */ }, + { 2047, 0, 11, + MAD_F(0x10020040) /* 1.00048851979 => 1.00048851967, e 0.00000000012 */, + MAD_F(0x00040000) /* 0.00097656250 => 0.00097656250, e 0.00000000000 */ }, + { 4095, 0, 12, + MAD_F(0x10010010) /* 1.00024420024 => 1.00024420023, e 0.00000000001 */, + MAD_F(0x00020000) /* 0.00048828125 => 0.00048828125, e 0.00000000000 */ }, + { 8191, 0, 13, + MAD_F(0x10008004) /* 1.00012208522 => 1.00012208521, e 0.00000000001 */, + MAD_F(0x00010000) /* 0.00024414063 => 0.00024414062, e 0.00000000000 */ }, + { 16383, 0, 14, + MAD_F(0x10004001) /* 1.00006103888 => 1.00006103888, e -0.00000000000 */, + MAD_F(0x00008000) /* 0.00012207031 => 0.00012207031, e -0.00000000000 */ }, + { 32767, 0, 15, + MAD_F(0x10002000) /* 1.00003051851 => 1.00003051758, e 0.00000000093 */, + MAD_F(0x00004000) /* 0.00006103516 => 0.00006103516, e 0.00000000000 */ }, + { 65535, 0, 16, + MAD_F(0x10001000) /* 1.00001525902 => 1.00001525879, e 0.00000000023 */, + MAD_F(0x00002000) /* 0.00003051758 => 0.00003051758, e 0.00000000000 */ } diff --git a/core/multimedia/opieplayer/libmad/qpe-libmadplugin.control b/core/multimedia/opieplayer/libmad/qpe-libmadplugin.control new file mode 100644 index 0000000..077350c --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/qpe-libmadplugin.control @@ -0,0 +1,9 @@ +Files: plugins/codecs/libmadplugin.so.1.0.0 plugins/codecs/libmadplugin.so.1.0 plugins/codecs/libmadplugin.so.1 plugins/codecs/libmadplugin.so +Priority: optional +Section: qpe/plugins +Maintainer: John Ryland +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: MP3 file plugin using libmad + Plugin to play MP3 files with the mediaplayer in the Qtopia environment. diff --git a/core/multimedia/opieplayer/libmad/rq_table.dat b/core/multimedia/opieplayer/libmad/rq_table.dat new file mode 100644 index 0000000..b6d1634 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/rq_table.dat @@ -0,0 +1,8747 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +/* + * This is the lookup table used to compute x^(4/3) for Layer III + * requantization. To maintain the best possible accuracy, the value is + * stored as a normalized mantissa with exponent. The requantization + * algorithm recombines these parts with appropriate scaling. + */ + + /* 0 */ { MAD_F(0x00000000) /* 0.000000000 */, 0 }, + /* 1 */ { MAD_F(0x04000000) /* 0.250000000 */, 2 }, + /* 2 */ { MAD_F(0x050a28be) /* 0.314980262 */, 3 }, + /* 3 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 4 }, + /* 4 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 4 }, + /* 5 */ { MAD_F(0x04466275) /* 0.267183742 */, 5 }, + /* 6 */ { MAD_F(0x05738c72) /* 0.340710111 */, 5 }, + /* 7 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 5 }, + /* 8 */ { MAD_F(0x04000000) /* 0.250000000 */, 6 }, + /* 9 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 6 }, + /* 10 */ { MAD_F(0x0562d694) /* 0.336630420 */, 6 }, + /* 11 */ { MAD_F(0x061dae96) /* 0.382246578 */, 6 }, + /* 12 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 6 }, + /* 13 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 6 }, + /* 14 */ { MAD_F(0x0437be65) /* 0.263609310 */, 7 }, + /* 15 */ { MAD_F(0x049fc824) /* 0.289009227 */, 7 }, + + /* 16 */ { MAD_F(0x050a28be) /* 0.314980262 */, 7 }, + /* 17 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 7 }, + /* 18 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 7 }, + /* 19 */ { MAD_F(0x06566361) /* 0.396090870 */, 7 }, + /* 20 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 7 }, + /* 21 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 7 }, + /* 22 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 7 }, + /* 23 */ { MAD_F(0x04168b05) /* 0.255503674 */, 8 }, + /* 24 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 8 }, + /* 25 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 8 }, + /* 26 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 8 }, + /* 27 */ { MAD_F(0x05100000) /* 0.316406250 */, 8 }, + /* 28 */ { MAD_F(0x05506451) /* 0.332126919 */, 8 }, + /* 29 */ { MAD_F(0x05918e15) /* 0.348035890 */, 8 }, + /* 30 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 8 }, + /* 31 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 8 }, + + /* 32 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 8 }, + /* 33 */ { MAD_F(0x069d9400) /* 0.413471222 */, 8 }, + /* 34 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 8 }, + /* 35 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 8 }, + /* 36 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 8 }, + /* 37 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 8 }, + /* 38 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 8 }, + /* 39 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 9 }, + /* 40 */ { MAD_F(0x04466275) /* 0.267183742 */, 9 }, + /* 41 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 9 }, + /* 42 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 9 }, + /* 43 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 9 }, + /* 44 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 9 }, + /* 45 */ { MAD_F(0x05007b49) /* 0.312617576 */, 9 }, + /* 46 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 9 }, + /* 47 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 9 }, + + /* 48 */ { MAD_F(0x05738c72) /* 0.340710111 */, 9 }, + /* 49 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 9 }, + /* 50 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 9 }, + /* 51 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 9 }, + /* 52 */ { MAD_F(0x0610b982) /* 0.379083164 */, 9 }, + /* 53 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 9 }, + /* 54 */ { MAD_F(0x0660db91) /* 0.398646895 */, 9 }, + /* 55 */ { MAD_F(0x06894c90) /* 0.408520284 */, 9 }, + /* 56 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 9 }, + /* 57 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 9 }, + /* 58 */ { MAD_F(0x07041636) /* 0.438497744 */, 9 }, + /* 59 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 9 }, + /* 60 */ { MAD_F(0x075722ef) /* 0.458773552 */, 9 }, + /* 61 */ { MAD_F(0x078102b8) /* 0.468996735 */, 9 }, + /* 62 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 9 }, + /* 63 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 9 }, + + /* 64 */ { MAD_F(0x04000000) /* 0.250000000 */, 10 }, + /* 65 */ { MAD_F(0x04156381) /* 0.255221850 */, 10 }, + /* 66 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 10 }, + /* 67 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 10 }, + /* 68 */ { MAD_F(0x045635cf) /* 0.271047409 */, 10 }, + /* 69 */ { MAD_F(0x046c083e) /* 0.276375048 */, 10 }, + /* 70 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 10 }, + /* 71 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 10 }, + /* 72 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 10 }, + /* 73 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 10 }, + /* 74 */ { MAD_F(0x04dab524) /* 0.303395408 */, 10 }, + /* 75 */ { MAD_F(0x04f12624) /* 0.308874267 */, 10 }, + /* 76 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 10 }, + /* 77 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 10 }, + /* 78 */ { MAD_F(0x053511cb) /* 0.325456423 */, 10 }, + /* 79 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 10 }, + + /* 80 */ { MAD_F(0x0562d694) /* 0.336630420 */, 10 }, + /* 81 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 10 }, + /* 82 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 10 }, + /* 83 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 10 }, + /* 84 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 10 }, + /* 85 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 10 }, + /* 86 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 10 }, + /* 87 */ { MAD_F(0x0606012b) /* 0.376465960 */, 10 }, + /* 88 */ { MAD_F(0x061dae96) /* 0.382246578 */, 10 }, + /* 89 */ { MAD_F(0x06357302) /* 0.388049134 */, 10 }, + /* 90 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 10 }, + /* 91 */ { MAD_F(0x0665402d) /* 0.399719406 */, 10 }, + /* 92 */ { MAD_F(0x067d4896) /* 0.405586801 */, 10 }, + /* 93 */ { MAD_F(0x06956753) /* 0.411475493 */, 10 }, + /* 94 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 10 }, + /* 95 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 10 }, + + /* 96 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 10 }, + /* 97 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 10 }, + /* 98 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 10 }, + /* 99 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 10 }, + /* 100 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 10 }, + /* 101 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 10 }, + /* 102 */ { MAD_F(0x07724f64) /* 0.465407744 */, 10 }, + /* 103 */ { MAD_F(0x078b4514) /* 0.471501425 */, 10 }, + /* 104 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 10 }, + /* 105 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 10 }, + /* 106 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 10 }, + /* 107 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 10 }, + /* 108 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 11 }, + /* 109 */ { MAD_F(0x04115aca) /* 0.254236974 */, 11 }, + /* 110 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 11 }, + /* 111 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 11 }, + + /* 112 */ { MAD_F(0x0437be65) /* 0.263609310 */, 11 }, + /* 113 */ { MAD_F(0x04449dee) /* 0.266752177 */, 11 }, + /* 114 */ { MAD_F(0x04518733) /* 0.269904329 */, 11 }, + /* 115 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 11 }, + /* 116 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 11 }, + /* 117 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 11 }, + /* 118 */ { MAD_F(0x04858c83) /* 0.282604707 */, 11 }, + /* 119 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 11 }, + /* 120 */ { MAD_F(0x049fc824) /* 0.289009227 */, 11 }, + /* 121 */ { MAD_F(0x04acf402) /* 0.292224893 */, 11 }, + /* 122 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 11 }, + /* 123 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 11 }, + /* 124 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 11 }, + /* 125 */ { MAD_F(0x04e20000) /* 0.305175781 */, 11 }, + /* 126 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 11 }, + /* 127 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 11 }, + + /* 128 */ { MAD_F(0x050a28be) /* 0.314980262 */, 11 }, + /* 129 */ { MAD_F(0x05179da4) /* 0.318265572 */, 11 }, + /* 130 */ { MAD_F(0x05251b73) /* 0.321559381 */, 11 }, + /* 131 */ { MAD_F(0x0532a220) /* 0.324861647 */, 11 }, + /* 132 */ { MAD_F(0x054031a0) /* 0.328172327 */, 11 }, + /* 133 */ { MAD_F(0x054dc9e7) /* 0.331491377 */, 11 }, + /* 134 */ { MAD_F(0x055b6ae9) /* 0.334818756 */, 11 }, + /* 135 */ { MAD_F(0x0569149c) /* 0.338154423 */, 11 }, + /* 136 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 11 }, + /* 137 */ { MAD_F(0x058481e9) /* 0.344850455 */, 11 }, + /* 138 */ { MAD_F(0x0592456d) /* 0.348210741 */, 11 }, + /* 139 */ { MAD_F(0x05a01176) /* 0.351579152 */, 11 }, + /* 140 */ { MAD_F(0x05ade5fa) /* 0.354955651 */, 11 }, + /* 141 */ { MAD_F(0x05bbc2ef) /* 0.358340200 */, 11 }, + /* 142 */ { MAD_F(0x05c9a84a) /* 0.361732758 */, 11 }, + /* 143 */ { MAD_F(0x05d79601) /* 0.365133291 */, 11 }, + + /* 144 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 11 }, + /* 145 */ { MAD_F(0x05f38a5d) /* 0.371958126 */, 11 }, + /* 146 */ { MAD_F(0x060190ee) /* 0.375382356 */, 11 }, + /* 147 */ { MAD_F(0x060f9fb3) /* 0.378814413 */, 11 }, + /* 148 */ { MAD_F(0x061db6a5) /* 0.382254261 */, 11 }, + /* 149 */ { MAD_F(0x062bd5b8) /* 0.385701865 */, 11 }, + /* 150 */ { MAD_F(0x0639fce4) /* 0.389157191 */, 11 }, + /* 151 */ { MAD_F(0x06482c1f) /* 0.392620204 */, 11 }, + /* 152 */ { MAD_F(0x06566361) /* 0.396090870 */, 11 }, + /* 153 */ { MAD_F(0x0664a2a0) /* 0.399569155 */, 11 }, + /* 154 */ { MAD_F(0x0672e9d4) /* 0.403055027 */, 11 }, + /* 155 */ { MAD_F(0x068138f3) /* 0.406548452 */, 11 }, + /* 156 */ { MAD_F(0x068f8ff5) /* 0.410049398 */, 11 }, + /* 157 */ { MAD_F(0x069deed1) /* 0.413557833 */, 11 }, + /* 158 */ { MAD_F(0x06ac557f) /* 0.417073724 */, 11 }, + /* 159 */ { MAD_F(0x06bac3f6) /* 0.420597041 */, 11 }, + + /* 160 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 11 }, + /* 161 */ { MAD_F(0x06d7b81f) /* 0.427665827 */, 11 }, + /* 162 */ { MAD_F(0x06e63dc0) /* 0.431211234 */, 11 }, + /* 163 */ { MAD_F(0x06f4cb09) /* 0.434763944 */, 11 }, + /* 164 */ { MAD_F(0x07035ff3) /* 0.438323927 */, 11 }, + /* 165 */ { MAD_F(0x0711fc75) /* 0.441891153 */, 11 }, + /* 166 */ { MAD_F(0x0720a087) /* 0.445465593 */, 11 }, + /* 167 */ { MAD_F(0x072f4c22) /* 0.449047217 */, 11 }, + /* 168 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 11 }, + /* 169 */ { MAD_F(0x074cb9d3) /* 0.456231906 */, 11 }, + /* 170 */ { MAD_F(0x075b7bdb) /* 0.459834914 */, 11 }, + /* 171 */ { MAD_F(0x076a454c) /* 0.463444993 */, 11 }, + /* 172 */ { MAD_F(0x07791620) /* 0.467062117 */, 11 }, + /* 173 */ { MAD_F(0x0787ee50) /* 0.470686258 */, 11 }, + /* 174 */ { MAD_F(0x0796cdd4) /* 0.474317388 */, 11 }, + /* 175 */ { MAD_F(0x07a5b4a5) /* 0.477955481 */, 11 }, + + /* 176 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 11 }, + /* 177 */ { MAD_F(0x07c39812) /* 0.485252449 */, 11 }, + /* 178 */ { MAD_F(0x07d294a0) /* 0.488911273 */, 11 }, + /* 179 */ { MAD_F(0x07e1985f) /* 0.492576954 */, 11 }, + /* 180 */ { MAD_F(0x07f0a348) /* 0.496249468 */, 11 }, + /* 181 */ { MAD_F(0x07ffb554) /* 0.499928790 */, 11 }, + /* 182 */ { MAD_F(0x0407673f) /* 0.251807447 */, 12 }, + /* 183 */ { MAD_F(0x040ef75e) /* 0.253653877 */, 12 }, + /* 184 */ { MAD_F(0x04168b05) /* 0.255503674 */, 12 }, + /* 185 */ { MAD_F(0x041e2230) /* 0.257356825 */, 12 }, + /* 186 */ { MAD_F(0x0425bcdd) /* 0.259213318 */, 12 }, + /* 187 */ { MAD_F(0x042d5b07) /* 0.261073141 */, 12 }, + /* 188 */ { MAD_F(0x0434fcad) /* 0.262936282 */, 12 }, + /* 189 */ { MAD_F(0x043ca1c9) /* 0.264802730 */, 12 }, + /* 190 */ { MAD_F(0x04444a5a) /* 0.266672472 */, 12 }, + /* 191 */ { MAD_F(0x044bf65d) /* 0.268545497 */, 12 }, + + /* 192 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 12 }, + /* 193 */ { MAD_F(0x045b58a9) /* 0.272301352 */, 12 }, + /* 194 */ { MAD_F(0x04630eed) /* 0.274184158 */, 12 }, + /* 195 */ { MAD_F(0x046ac896) /* 0.276070203 */, 12 }, + /* 196 */ { MAD_F(0x047285a2) /* 0.277959474 */, 12 }, + /* 197 */ { MAD_F(0x047a460c) /* 0.279851960 */, 12 }, + /* 198 */ { MAD_F(0x048209d3) /* 0.281747652 */, 12 }, + /* 199 */ { MAD_F(0x0489d0f4) /* 0.283646538 */, 12 }, + /* 200 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 12 }, + /* 201 */ { MAD_F(0x04996935) /* 0.287453849 */, 12 }, + /* 202 */ { MAD_F(0x04a13a50) /* 0.289362253 */, 12 }, + /* 203 */ { MAD_F(0x04a90eba) /* 0.291273810 */, 12 }, + /* 204 */ { MAD_F(0x04b0e66e) /* 0.293188507 */, 12 }, + /* 205 */ { MAD_F(0x04b8c16c) /* 0.295106336 */, 12 }, + /* 206 */ { MAD_F(0x04c09faf) /* 0.297027285 */, 12 }, + /* 207 */ { MAD_F(0x04c88135) /* 0.298951346 */, 12 }, + + /* 208 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 12 }, + /* 209 */ { MAD_F(0x04d84dff) /* 0.302808759 */, 12 }, + /* 210 */ { MAD_F(0x04e0393e) /* 0.304742092 */, 12 }, + /* 211 */ { MAD_F(0x04e827b6) /* 0.306678497 */, 12 }, + /* 212 */ { MAD_F(0x04f01963) /* 0.308617963 */, 12 }, + /* 213 */ { MAD_F(0x04f80e44) /* 0.310560480 */, 12 }, + /* 214 */ { MAD_F(0x05000655) /* 0.312506041 */, 12 }, + /* 215 */ { MAD_F(0x05080195) /* 0.314454634 */, 12 }, + /* 216 */ { MAD_F(0x05100000) /* 0.316406250 */, 12 }, + /* 217 */ { MAD_F(0x05180194) /* 0.318360880 */, 12 }, + /* 218 */ { MAD_F(0x0520064f) /* 0.320318516 */, 12 }, + /* 219 */ { MAD_F(0x05280e2d) /* 0.322279147 */, 12 }, + /* 220 */ { MAD_F(0x0530192e) /* 0.324242764 */, 12 }, + /* 221 */ { MAD_F(0x0538274e) /* 0.326209359 */, 12 }, + /* 222 */ { MAD_F(0x0540388a) /* 0.328178922 */, 12 }, + /* 223 */ { MAD_F(0x05484ce2) /* 0.330151445 */, 12 }, + + /* 224 */ { MAD_F(0x05506451) /* 0.332126919 */, 12 }, + /* 225 */ { MAD_F(0x05587ed5) /* 0.334105334 */, 12 }, + /* 226 */ { MAD_F(0x05609c6e) /* 0.336086683 */, 12 }, + /* 227 */ { MAD_F(0x0568bd17) /* 0.338070956 */, 12 }, + /* 228 */ { MAD_F(0x0570e0cf) /* 0.340058145 */, 12 }, + /* 229 */ { MAD_F(0x05790793) /* 0.342048241 */, 12 }, + /* 230 */ { MAD_F(0x05813162) /* 0.344041237 */, 12 }, + /* 231 */ { MAD_F(0x05895e39) /* 0.346037122 */, 12 }, + /* 232 */ { MAD_F(0x05918e15) /* 0.348035890 */, 12 }, + /* 233 */ { MAD_F(0x0599c0f4) /* 0.350037532 */, 12 }, + /* 234 */ { MAD_F(0x05a1f6d5) /* 0.352042040 */, 12 }, + /* 235 */ { MAD_F(0x05aa2fb5) /* 0.354049405 */, 12 }, + /* 236 */ { MAD_F(0x05b26b92) /* 0.356059619 */, 12 }, + /* 237 */ { MAD_F(0x05baaa69) /* 0.358072674 */, 12 }, + /* 238 */ { MAD_F(0x05c2ec39) /* 0.360088563 */, 12 }, + /* 239 */ { MAD_F(0x05cb3100) /* 0.362107278 */, 12 }, + + /* 240 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 12 }, + /* 241 */ { MAD_F(0x05dbc368) /* 0.366153151 */, 12 }, + /* 242 */ { MAD_F(0x05e41105) /* 0.368180294 */, 12 }, + /* 243 */ { MAD_F(0x05ec6190) /* 0.370210231 */, 12 }, + /* 244 */ { MAD_F(0x05f4b507) /* 0.372242955 */, 12 }, + /* 245 */ { MAD_F(0x05fd0b68) /* 0.374278458 */, 12 }, + /* 246 */ { MAD_F(0x060564b1) /* 0.376316732 */, 12 }, + /* 247 */ { MAD_F(0x060dc0e0) /* 0.378357769 */, 12 }, + /* 248 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 12 }, + /* 249 */ { MAD_F(0x061e81e8) /* 0.382448106 */, 12 }, + /* 250 */ { MAD_F(0x0626e6bc) /* 0.384497391 */, 12 }, + /* 251 */ { MAD_F(0x062f4e6f) /* 0.386549409 */, 12 }, + /* 252 */ { MAD_F(0x0637b8fd) /* 0.388604155 */, 12 }, + /* 253 */ { MAD_F(0x06402666) /* 0.390661620 */, 12 }, + /* 254 */ { MAD_F(0x064896a7) /* 0.392721798 */, 12 }, + /* 255 */ { MAD_F(0x065109be) /* 0.394784681 */, 12 }, + + /* 256 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 12 }, + /* 257 */ { MAD_F(0x0661f867) /* 0.398918536 */, 12 }, + /* 258 */ { MAD_F(0x066a73f5) /* 0.400989493 */, 12 }, + /* 259 */ { MAD_F(0x0672f252) /* 0.403063128 */, 12 }, + /* 260 */ { MAD_F(0x067b737c) /* 0.405139433 */, 12 }, + /* 261 */ { MAD_F(0x0683f771) /* 0.407218402 */, 12 }, + /* 262 */ { MAD_F(0x068c7e2f) /* 0.409300027 */, 12 }, + /* 263 */ { MAD_F(0x069507b5) /* 0.411384303 */, 12 }, + /* 264 */ { MAD_F(0x069d9400) /* 0.413471222 */, 12 }, + /* 265 */ { MAD_F(0x06a6230f) /* 0.415560778 */, 12 }, + /* 266 */ { MAD_F(0x06aeb4e0) /* 0.417652964 */, 12 }, + /* 267 */ { MAD_F(0x06b74971) /* 0.419747773 */, 12 }, + /* 268 */ { MAD_F(0x06bfe0c0) /* 0.421845199 */, 12 }, + /* 269 */ { MAD_F(0x06c87acc) /* 0.423945235 */, 12 }, + /* 270 */ { MAD_F(0x06d11794) /* 0.426047876 */, 12 }, + /* 271 */ { MAD_F(0x06d9b714) /* 0.428153114 */, 12 }, + + /* 272 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 12 }, + /* 273 */ { MAD_F(0x06eafe3a) /* 0.432371356 */, 12 }, + /* 274 */ { MAD_F(0x06f3a5dc) /* 0.434484348 */, 12 }, + /* 275 */ { MAD_F(0x06fc5030) /* 0.436599912 */, 12 }, + /* 276 */ { MAD_F(0x0704fd35) /* 0.438718042 */, 12 }, + /* 277 */ { MAD_F(0x070dacea) /* 0.440838732 */, 12 }, + /* 278 */ { MAD_F(0x07165f4b) /* 0.442961975 */, 12 }, + /* 279 */ { MAD_F(0x071f1459) /* 0.445087765 */, 12 }, + /* 280 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 12 }, + /* 281 */ { MAD_F(0x07308671) /* 0.449346964 */, 12 }, + /* 282 */ { MAD_F(0x07394378) /* 0.451480360 */, 12 }, + /* 283 */ { MAD_F(0x07420325) /* 0.453616280 */, 12 }, + /* 284 */ { MAD_F(0x074ac575) /* 0.455754717 */, 12 }, + /* 285 */ { MAD_F(0x07538a67) /* 0.457895665 */, 12 }, + /* 286 */ { MAD_F(0x075c51fa) /* 0.460039119 */, 12 }, + /* 287 */ { MAD_F(0x07651c2c) /* 0.462185072 */, 12 }, + + /* 288 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 12 }, + /* 289 */ { MAD_F(0x0776b867) /* 0.466484455 */, 12 }, + /* 290 */ { MAD_F(0x077f8a6d) /* 0.468637872 */, 12 }, + /* 291 */ { MAD_F(0x07885f0b) /* 0.470793767 */, 12 }, + /* 292 */ { MAD_F(0x07913641) /* 0.472952132 */, 12 }, + /* 293 */ { MAD_F(0x079a100c) /* 0.475112962 */, 12 }, + /* 294 */ { MAD_F(0x07a2ec6c) /* 0.477276252 */, 12 }, + /* 295 */ { MAD_F(0x07abcb5f) /* 0.479441997 */, 12 }, + /* 296 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 12 }, + /* 297 */ { MAD_F(0x07bd90f6) /* 0.483780825 */, 12 }, + /* 298 */ { MAD_F(0x07c67798) /* 0.485953899 */, 12 }, + /* 299 */ { MAD_F(0x07cf60c7) /* 0.488129404 */, 12 }, + /* 300 */ { MAD_F(0x07d84c81) /* 0.490307336 */, 12 }, + /* 301 */ { MAD_F(0x07e13ac5) /* 0.492487690 */, 12 }, + /* 302 */ { MAD_F(0x07ea2b92) /* 0.494670459 */, 12 }, + /* 303 */ { MAD_F(0x07f31ee6) /* 0.496855639 */, 12 }, + + /* 304 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 12 }, + /* 305 */ { MAD_F(0x0402868e) /* 0.250616605 */, 13 }, + /* 306 */ { MAD_F(0x040703ff) /* 0.251712795 */, 13 }, + /* 307 */ { MAD_F(0x040b82b0) /* 0.252810180 */, 13 }, + /* 308 */ { MAD_F(0x041002a1) /* 0.253908756 */, 13 }, + /* 309 */ { MAD_F(0x041483d1) /* 0.255008523 */, 13 }, + /* 310 */ { MAD_F(0x04190640) /* 0.256109476 */, 13 }, + /* 311 */ { MAD_F(0x041d89ed) /* 0.257211614 */, 13 }, + /* 312 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 13 }, + /* 313 */ { MAD_F(0x042694fe) /* 0.259419433 */, 13 }, + /* 314 */ { MAD_F(0x042b1c60) /* 0.260525110 */, 13 }, + /* 315 */ { MAD_F(0x042fa4fe) /* 0.261631960 */, 13 }, + /* 316 */ { MAD_F(0x04342ed7) /* 0.262739982 */, 13 }, + /* 317 */ { MAD_F(0x0438b9e9) /* 0.263849174 */, 13 }, + /* 318 */ { MAD_F(0x043d4635) /* 0.264959533 */, 13 }, + /* 319 */ { MAD_F(0x0441d3b9) /* 0.266071056 */, 13 }, + + /* 320 */ { MAD_F(0x04466275) /* 0.267183742 */, 13 }, + /* 321 */ { MAD_F(0x044af269) /* 0.268297587 */, 13 }, + /* 322 */ { MAD_F(0x044f8393) /* 0.269412589 */, 13 }, + /* 323 */ { MAD_F(0x045415f3) /* 0.270528746 */, 13 }, + /* 324 */ { MAD_F(0x0458a989) /* 0.271646056 */, 13 }, + /* 325 */ { MAD_F(0x045d3e53) /* 0.272764515 */, 13 }, + /* 326 */ { MAD_F(0x0461d451) /* 0.273884123 */, 13 }, + /* 327 */ { MAD_F(0x04666b83) /* 0.275004875 */, 13 }, + /* 328 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 13 }, + /* 329 */ { MAD_F(0x046f9d7e) /* 0.277249808 */, 13 }, + /* 330 */ { MAD_F(0x04743847) /* 0.278373983 */, 13 }, + /* 331 */ { MAD_F(0x0478d440) /* 0.279499294 */, 13 }, + /* 332 */ { MAD_F(0x047d716a) /* 0.280625739 */, 13 }, + /* 333 */ { MAD_F(0x04820fc3) /* 0.281753315 */, 13 }, + /* 334 */ { MAD_F(0x0486af4c) /* 0.282882021 */, 13 }, + /* 335 */ { MAD_F(0x048b5003) /* 0.284011853 */, 13 }, + + /* 336 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 13 }, + /* 337 */ { MAD_F(0x049494fb) /* 0.286274891 */, 13 }, + /* 338 */ { MAD_F(0x0499393a) /* 0.287408091 */, 13 }, + /* 339 */ { MAD_F(0x049ddea5) /* 0.288542409 */, 13 }, + /* 340 */ { MAD_F(0x04a2853c) /* 0.289677844 */, 13 }, + /* 341 */ { MAD_F(0x04a72cfe) /* 0.290814392 */, 13 }, + /* 342 */ { MAD_F(0x04abd5ea) /* 0.291952051 */, 13 }, + /* 343 */ { MAD_F(0x04b08000) /* 0.293090820 */, 13 }, + /* 344 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 13 }, + /* 345 */ { MAD_F(0x04b9d7a7) /* 0.295371678 */, 13 }, + /* 346 */ { MAD_F(0x04be8537) /* 0.296513762 */, 13 }, + /* 347 */ { MAD_F(0x04c333ee) /* 0.297656947 */, 13 }, + /* 348 */ { MAD_F(0x04c7e3cc) /* 0.298801231 */, 13 }, + /* 349 */ { MAD_F(0x04cc94d1) /* 0.299946611 */, 13 }, + /* 350 */ { MAD_F(0x04d146fb) /* 0.301093085 */, 13 }, + /* 351 */ { MAD_F(0x04d5fa4b) /* 0.302240653 */, 13 }, + + /* 352 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 13 }, + /* 353 */ { MAD_F(0x04df6458) /* 0.304539056 */, 13 }, + /* 354 */ { MAD_F(0x04e41b14) /* 0.305689888 */, 13 }, + /* 355 */ { MAD_F(0x04e8d2f3) /* 0.306841804 */, 13 }, + /* 356 */ { MAD_F(0x04ed8bf5) /* 0.307994802 */, 13 }, + /* 357 */ { MAD_F(0x04f24618) /* 0.309148880 */, 13 }, + /* 358 */ { MAD_F(0x04f7015d) /* 0.310304037 */, 13 }, + /* 359 */ { MAD_F(0x04fbbdc3) /* 0.311460269 */, 13 }, + /* 360 */ { MAD_F(0x05007b49) /* 0.312617576 */, 13 }, + /* 361 */ { MAD_F(0x050539ef) /* 0.313775954 */, 13 }, + /* 362 */ { MAD_F(0x0509f9b4) /* 0.314935403 */, 13 }, + /* 363 */ { MAD_F(0x050eba98) /* 0.316095920 */, 13 }, + /* 364 */ { MAD_F(0x05137c9a) /* 0.317257503 */, 13 }, + /* 365 */ { MAD_F(0x05183fba) /* 0.318420150 */, 13 }, + /* 366 */ { MAD_F(0x051d03f7) /* 0.319583859 */, 13 }, + /* 367 */ { MAD_F(0x0521c950) /* 0.320748629 */, 13 }, + + /* 368 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 13 }, + /* 369 */ { MAD_F(0x052b5757) /* 0.323081342 */, 13 }, + /* 370 */ { MAD_F(0x05302003) /* 0.324249281 */, 13 }, + /* 371 */ { MAD_F(0x0534e9ca) /* 0.325418273 */, 13 }, + /* 372 */ { MAD_F(0x0539b4ab) /* 0.326588316 */, 13 }, + /* 373 */ { MAD_F(0x053e80a6) /* 0.327759407 */, 13 }, + /* 374 */ { MAD_F(0x05434db9) /* 0.328931546 */, 13 }, + /* 375 */ { MAD_F(0x05481be5) /* 0.330104730 */, 13 }, + /* 376 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 13 }, + /* 377 */ { MAD_F(0x0551bb85) /* 0.332454225 */, 13 }, + /* 378 */ { MAD_F(0x05568cf8) /* 0.333630533 */, 13 }, + /* 379 */ { MAD_F(0x055b5f81) /* 0.334807879 */, 13 }, + /* 380 */ { MAD_F(0x05603321) /* 0.335986261 */, 13 }, + /* 381 */ { MAD_F(0x056507d6) /* 0.337165677 */, 13 }, + /* 382 */ { MAD_F(0x0569dda0) /* 0.338346125 */, 13 }, + /* 383 */ { MAD_F(0x056eb47f) /* 0.339527604 */, 13 }, + + /* 384 */ { MAD_F(0x05738c72) /* 0.340710111 */, 13 }, + /* 385 */ { MAD_F(0x05786578) /* 0.341893646 */, 13 }, + /* 386 */ { MAD_F(0x057d3f92) /* 0.343078205 */, 13 }, + /* 387 */ { MAD_F(0x05821abf) /* 0.344263788 */, 13 }, + /* 388 */ { MAD_F(0x0586f6fd) /* 0.345450393 */, 13 }, + /* 389 */ { MAD_F(0x058bd44e) /* 0.346638017 */, 13 }, + /* 390 */ { MAD_F(0x0590b2b0) /* 0.347826659 */, 13 }, + /* 391 */ { MAD_F(0x05959222) /* 0.349016318 */, 13 }, + /* 392 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 13 }, + /* 393 */ { MAD_F(0x059f5438) /* 0.351398678 */, 13 }, + /* 394 */ { MAD_F(0x05a436da) /* 0.352591376 */, 13 }, + /* 395 */ { MAD_F(0x05a91a8c) /* 0.353785083 */, 13 }, + /* 396 */ { MAD_F(0x05adff4c) /* 0.354979798 */, 13 }, + /* 397 */ { MAD_F(0x05b2e51a) /* 0.356175519 */, 13 }, + /* 398 */ { MAD_F(0x05b7cbf5) /* 0.357372244 */, 13 }, + /* 399 */ { MAD_F(0x05bcb3de) /* 0.358569972 */, 13 }, + + /* 400 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 13 }, + /* 401 */ { MAD_F(0x05c686d5) /* 0.360968429 */, 13 }, + /* 402 */ { MAD_F(0x05cb71e2) /* 0.362169156 */, 13 }, + /* 403 */ { MAD_F(0x05d05dfb) /* 0.363370878 */, 13 }, + /* 404 */ { MAD_F(0x05d54b1f) /* 0.364573594 */, 13 }, + /* 405 */ { MAD_F(0x05da394d) /* 0.365777304 */, 13 }, + /* 406 */ { MAD_F(0x05df2885) /* 0.366982004 */, 13 }, + /* 407 */ { MAD_F(0x05e418c7) /* 0.368187694 */, 13 }, + /* 408 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 13 }, + /* 409 */ { MAD_F(0x05edfc66) /* 0.370602036 */, 13 }, + /* 410 */ { MAD_F(0x05f2efc2) /* 0.371810684 */, 13 }, + /* 411 */ { MAD_F(0x05f7e426) /* 0.373020316 */, 13 }, + /* 412 */ { MAD_F(0x05fcd992) /* 0.374230929 */, 13 }, + /* 413 */ { MAD_F(0x0601d004) /* 0.375442522 */, 13 }, + /* 414 */ { MAD_F(0x0606c77d) /* 0.376655093 */, 13 }, + /* 415 */ { MAD_F(0x060bbffd) /* 0.377868641 */, 13 }, + + /* 416 */ { MAD_F(0x0610b982) /* 0.379083164 */, 13 }, + /* 417 */ { MAD_F(0x0615b40c) /* 0.380298661 */, 13 }, + /* 418 */ { MAD_F(0x061aaf9c) /* 0.381515130 */, 13 }, + /* 419 */ { MAD_F(0x061fac2f) /* 0.382732569 */, 13 }, + /* 420 */ { MAD_F(0x0624a9c7) /* 0.383950977 */, 13 }, + /* 421 */ { MAD_F(0x0629a863) /* 0.385170352 */, 13 }, + /* 422 */ { MAD_F(0x062ea802) /* 0.386390694 */, 13 }, + /* 423 */ { MAD_F(0x0633a8a3) /* 0.387611999 */, 13 }, + /* 424 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 13 }, + /* 425 */ { MAD_F(0x063dacee) /* 0.390057497 */, 13 }, + /* 426 */ { MAD_F(0x0642b096) /* 0.391281687 */, 13 }, + /* 427 */ { MAD_F(0x0647b53f) /* 0.392506834 */, 13 }, + /* 428 */ { MAD_F(0x064cbae9) /* 0.393732939 */, 13 }, + /* 429 */ { MAD_F(0x0651c193) /* 0.394959999 */, 13 }, + /* 430 */ { MAD_F(0x0656c93d) /* 0.396188012 */, 13 }, + /* 431 */ { MAD_F(0x065bd1e7) /* 0.397416978 */, 13 }, + + /* 432 */ { MAD_F(0x0660db91) /* 0.398646895 */, 13 }, + /* 433 */ { MAD_F(0x0665e639) /* 0.399877761 */, 13 }, + /* 434 */ { MAD_F(0x066af1df) /* 0.401109575 */, 13 }, + /* 435 */ { MAD_F(0x066ffe84) /* 0.402342335 */, 13 }, + /* 436 */ { MAD_F(0x06750c26) /* 0.403576041 */, 13 }, + /* 437 */ { MAD_F(0x067a1ac6) /* 0.404810690 */, 13 }, + /* 438 */ { MAD_F(0x067f2a62) /* 0.406046281 */, 13 }, + /* 439 */ { MAD_F(0x06843afb) /* 0.407282813 */, 13 }, + /* 440 */ { MAD_F(0x06894c90) /* 0.408520284 */, 13 }, + /* 441 */ { MAD_F(0x068e5f21) /* 0.409758693 */, 13 }, + /* 442 */ { MAD_F(0x069372ae) /* 0.410998038 */, 13 }, + /* 443 */ { MAD_F(0x06988735) /* 0.412238319 */, 13 }, + /* 444 */ { MAD_F(0x069d9cb7) /* 0.413479532 */, 13 }, + /* 445 */ { MAD_F(0x06a2b333) /* 0.414721679 */, 13 }, + /* 446 */ { MAD_F(0x06a7caa9) /* 0.415964756 */, 13 }, + /* 447 */ { MAD_F(0x06ace318) /* 0.417208762 */, 13 }, + + /* 448 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 13 }, + /* 449 */ { MAD_F(0x06b716e2) /* 0.419699557 */, 13 }, + /* 450 */ { MAD_F(0x06bc323b) /* 0.420946343 */, 13 }, + /* 451 */ { MAD_F(0x06c14e8d) /* 0.422194054 */, 13 }, + /* 452 */ { MAD_F(0x06c66bd6) /* 0.423442686 */, 13 }, + /* 453 */ { MAD_F(0x06cb8a17) /* 0.424692240 */, 13 }, + /* 454 */ { MAD_F(0x06d0a94e) /* 0.425942714 */, 13 }, + /* 455 */ { MAD_F(0x06d5c97c) /* 0.427194106 */, 13 }, + /* 456 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 13 }, + /* 457 */ { MAD_F(0x06e00cbb) /* 0.429699640 */, 13 }, + /* 458 */ { MAD_F(0x06e52fca) /* 0.430953779 */, 13 }, + /* 459 */ { MAD_F(0x06ea53cf) /* 0.432208832 */, 13 }, + /* 460 */ { MAD_F(0x06ef78c8) /* 0.433464796 */, 13 }, + /* 461 */ { MAD_F(0x06f49eb6) /* 0.434721671 */, 13 }, + /* 462 */ { MAD_F(0x06f9c597) /* 0.435979455 */, 13 }, + /* 463 */ { MAD_F(0x06feed6d) /* 0.437238146 */, 13 }, + + /* 464 */ { MAD_F(0x07041636) /* 0.438497744 */, 13 }, + /* 465 */ { MAD_F(0x07093ff2) /* 0.439758248 */, 13 }, + /* 466 */ { MAD_F(0x070e6aa0) /* 0.441019655 */, 13 }, + /* 467 */ { MAD_F(0x07139641) /* 0.442281965 */, 13 }, + /* 468 */ { MAD_F(0x0718c2d3) /* 0.443545176 */, 13 }, + /* 469 */ { MAD_F(0x071df058) /* 0.444809288 */, 13 }, + /* 470 */ { MAD_F(0x07231ecd) /* 0.446074298 */, 13 }, + /* 471 */ { MAD_F(0x07284e34) /* 0.447340205 */, 13 }, + /* 472 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 13 }, + /* 473 */ { MAD_F(0x0732afd2) /* 0.449874708 */, 13 }, + /* 474 */ { MAD_F(0x0737e209) /* 0.451143300 */, 13 }, + /* 475 */ { MAD_F(0x073d1530) /* 0.452412785 */, 13 }, + /* 476 */ { MAD_F(0x07424946) /* 0.453683161 */, 13 }, + /* 477 */ { MAD_F(0x07477e4b) /* 0.454954427 */, 13 }, + /* 478 */ { MAD_F(0x074cb43e) /* 0.456226581 */, 13 }, + /* 479 */ { MAD_F(0x0751eb20) /* 0.457499623 */, 13 }, + + /* 480 */ { MAD_F(0x075722ef) /* 0.458773552 */, 13 }, + /* 481 */ { MAD_F(0x075c5bac) /* 0.460048365 */, 13 }, + /* 482 */ { MAD_F(0x07619557) /* 0.461324062 */, 13 }, + /* 483 */ { MAD_F(0x0766cfee) /* 0.462600642 */, 13 }, + /* 484 */ { MAD_F(0x076c0b72) /* 0.463878102 */, 13 }, + /* 485 */ { MAD_F(0x077147e2) /* 0.465156443 */, 13 }, + /* 486 */ { MAD_F(0x0776853e) /* 0.466435663 */, 13 }, + /* 487 */ { MAD_F(0x077bc385) /* 0.467715761 */, 13 }, + /* 488 */ { MAD_F(0x078102b8) /* 0.468996735 */, 13 }, + /* 489 */ { MAD_F(0x078642d6) /* 0.470278584 */, 13 }, + /* 490 */ { MAD_F(0x078b83de) /* 0.471561307 */, 13 }, + /* 491 */ { MAD_F(0x0790c5d1) /* 0.472844904 */, 13 }, + /* 492 */ { MAD_F(0x079608ae) /* 0.474129372 */, 13 }, + /* 493 */ { MAD_F(0x079b4c74) /* 0.475414710 */, 13 }, + /* 494 */ { MAD_F(0x07a09124) /* 0.476700918 */, 13 }, + /* 495 */ { MAD_F(0x07a5d6bd) /* 0.477987994 */, 13 }, + + /* 496 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 13 }, + /* 497 */ { MAD_F(0x07b064a8) /* 0.480564746 */, 13 }, + /* 498 */ { MAD_F(0x07b5acfb) /* 0.481854420 */, 13 }, + /* 499 */ { MAD_F(0x07baf635) /* 0.483144957 */, 13 }, + /* 500 */ { MAD_F(0x07c04056) /* 0.484436356 */, 13 }, + /* 501 */ { MAD_F(0x07c58b5f) /* 0.485728617 */, 13 }, + /* 502 */ { MAD_F(0x07cad74e) /* 0.487021738 */, 13 }, + /* 503 */ { MAD_F(0x07d02424) /* 0.488315717 */, 13 }, + /* 504 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 13 }, + /* 505 */ { MAD_F(0x07dac083) /* 0.490906249 */, 13 }, + /* 506 */ { MAD_F(0x07e0100a) /* 0.492202799 */, 13 }, + /* 507 */ { MAD_F(0x07e56078) /* 0.493500203 */, 13 }, + /* 508 */ { MAD_F(0x07eab1ca) /* 0.494798460 */, 13 }, + /* 509 */ { MAD_F(0x07f00401) /* 0.496097570 */, 13 }, + /* 510 */ { MAD_F(0x07f5571d) /* 0.497397530 */, 13 }, + /* 511 */ { MAD_F(0x07faab1c) /* 0.498698341 */, 13 }, + + /* 512 */ { MAD_F(0x04000000) /* 0.250000000 */, 14 }, + /* 513 */ { MAD_F(0x0402aae3) /* 0.250651254 */, 14 }, + /* 514 */ { MAD_F(0x04055638) /* 0.251302930 */, 14 }, + /* 515 */ { MAD_F(0x040801ff) /* 0.251955030 */, 14 }, + /* 516 */ { MAD_F(0x040aae37) /* 0.252607552 */, 14 }, + /* 517 */ { MAD_F(0x040d5ae0) /* 0.253260495 */, 14 }, + /* 518 */ { MAD_F(0x041007fa) /* 0.253913860 */, 14 }, + /* 519 */ { MAD_F(0x0412b586) /* 0.254567645 */, 14 }, + /* 520 */ { MAD_F(0x04156381) /* 0.255221850 */, 14 }, + /* 521 */ { MAD_F(0x041811ee) /* 0.255876475 */, 14 }, + /* 522 */ { MAD_F(0x041ac0cb) /* 0.256531518 */, 14 }, + /* 523 */ { MAD_F(0x041d7018) /* 0.257186980 */, 14 }, + /* 524 */ { MAD_F(0x04201fd5) /* 0.257842860 */, 14 }, + /* 525 */ { MAD_F(0x0422d003) /* 0.258499157 */, 14 }, + /* 526 */ { MAD_F(0x042580a0) /* 0.259155872 */, 14 }, + /* 527 */ { MAD_F(0x042831ad) /* 0.259813002 */, 14 }, + + /* 528 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 14 }, + /* 529 */ { MAD_F(0x042d9516) /* 0.261128510 */, 14 }, + /* 530 */ { MAD_F(0x04304772) /* 0.261786886 */, 14 }, + /* 531 */ { MAD_F(0x0432fa3d) /* 0.262445676 */, 14 }, + /* 532 */ { MAD_F(0x0435ad76) /* 0.263104880 */, 14 }, + /* 533 */ { MAD_F(0x0438611f) /* 0.263764497 */, 14 }, + /* 534 */ { MAD_F(0x043b1536) /* 0.264424527 */, 14 }, + /* 535 */ { MAD_F(0x043dc9bc) /* 0.265084969 */, 14 }, + /* 536 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 14 }, + /* 537 */ { MAD_F(0x04433414) /* 0.266407088 */, 14 }, + /* 538 */ { MAD_F(0x0445e9e5) /* 0.267068763 */, 14 }, + /* 539 */ { MAD_F(0x0448a024) /* 0.267730848 */, 14 }, + /* 540 */ { MAD_F(0x044b56d1) /* 0.268393343 */, 14 }, + /* 541 */ { MAD_F(0x044e0dec) /* 0.269056248 */, 14 }, + /* 542 */ { MAD_F(0x0450c575) /* 0.269719560 */, 14 }, + /* 543 */ { MAD_F(0x04537d6b) /* 0.270383281 */, 14 }, + + /* 544 */ { MAD_F(0x045635cf) /* 0.271047409 */, 14 }, + /* 545 */ { MAD_F(0x0458ee9f) /* 0.271711944 */, 14 }, + /* 546 */ { MAD_F(0x045ba7dd) /* 0.272376886 */, 14 }, + /* 547 */ { MAD_F(0x045e6188) /* 0.273042234 */, 14 }, + /* 548 */ { MAD_F(0x04611ba0) /* 0.273707988 */, 14 }, + /* 549 */ { MAD_F(0x0463d625) /* 0.274374147 */, 14 }, + /* 550 */ { MAD_F(0x04669116) /* 0.275040710 */, 14 }, + /* 551 */ { MAD_F(0x04694c74) /* 0.275707677 */, 14 }, + /* 552 */ { MAD_F(0x046c083e) /* 0.276375048 */, 14 }, + /* 553 */ { MAD_F(0x046ec474) /* 0.277042822 */, 14 }, + /* 554 */ { MAD_F(0x04718116) /* 0.277710999 */, 14 }, + /* 555 */ { MAD_F(0x04743e25) /* 0.278379578 */, 14 }, + /* 556 */ { MAD_F(0x0476fb9f) /* 0.279048558 */, 14 }, + /* 557 */ { MAD_F(0x0479b984) /* 0.279717940 */, 14 }, + /* 558 */ { MAD_F(0x047c77d6) /* 0.280387722 */, 14 }, + /* 559 */ { MAD_F(0x047f3693) /* 0.281057905 */, 14 }, + + /* 560 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 14 }, + /* 561 */ { MAD_F(0x0484b54e) /* 0.282399469 */, 14 }, + /* 562 */ { MAD_F(0x0487754c) /* 0.283070849 */, 14 }, + /* 563 */ { MAD_F(0x048a35b6) /* 0.283742628 */, 14 }, + /* 564 */ { MAD_F(0x048cf68a) /* 0.284414805 */, 14 }, + /* 565 */ { MAD_F(0x048fb7c8) /* 0.285087379 */, 14 }, + /* 566 */ { MAD_F(0x04927972) /* 0.285760350 */, 14 }, + /* 567 */ { MAD_F(0x04953b85) /* 0.286433717 */, 14 }, + /* 568 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 14 }, + /* 569 */ { MAD_F(0x049ac0eb) /* 0.287781640 */, 14 }, + /* 570 */ { MAD_F(0x049d843e) /* 0.288456194 */, 14 }, + /* 571 */ { MAD_F(0x04a047fa) /* 0.289131142 */, 14 }, + /* 572 */ { MAD_F(0x04a30c20) /* 0.289806485 */, 14 }, + /* 573 */ { MAD_F(0x04a5d0af) /* 0.290482221 */, 14 }, + /* 574 */ { MAD_F(0x04a895a8) /* 0.291158351 */, 14 }, + /* 575 */ { MAD_F(0x04ab5b0b) /* 0.291834873 */, 14 }, + + /* 576 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 14 }, + /* 577 */ { MAD_F(0x04b0e70c) /* 0.293189094 */, 14 }, + /* 578 */ { MAD_F(0x04b3adaa) /* 0.293866792 */, 14 }, + /* 579 */ { MAD_F(0x04b674b1) /* 0.294544881 */, 14 }, + /* 580 */ { MAD_F(0x04b93c21) /* 0.295223360 */, 14 }, + /* 581 */ { MAD_F(0x04bc03fa) /* 0.295902229 */, 14 }, + /* 582 */ { MAD_F(0x04becc3b) /* 0.296581488 */, 14 }, + /* 583 */ { MAD_F(0x04c194e4) /* 0.297261136 */, 14 }, + /* 584 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 14 }, + /* 585 */ { MAD_F(0x04c72771) /* 0.298621598 */, 14 }, + /* 586 */ { MAD_F(0x04c9f153) /* 0.299302411 */, 14 }, + /* 587 */ { MAD_F(0x04ccbb9d) /* 0.299983611 */, 14 }, + /* 588 */ { MAD_F(0x04cf864f) /* 0.300665198 */, 14 }, + /* 589 */ { MAD_F(0x04d25169) /* 0.301347172 */, 14 }, + /* 590 */ { MAD_F(0x04d51ceb) /* 0.302029532 */, 14 }, + /* 591 */ { MAD_F(0x04d7e8d4) /* 0.302712277 */, 14 }, + + /* 592 */ { MAD_F(0x04dab524) /* 0.303395408 */, 14 }, + /* 593 */ { MAD_F(0x04dd81dc) /* 0.304078923 */, 14 }, + /* 594 */ { MAD_F(0x04e04efb) /* 0.304762823 */, 14 }, + /* 595 */ { MAD_F(0x04e31c81) /* 0.305447106 */, 14 }, + /* 596 */ { MAD_F(0x04e5ea6e) /* 0.306131773 */, 14 }, + /* 597 */ { MAD_F(0x04e8b8c2) /* 0.306816823 */, 14 }, + /* 598 */ { MAD_F(0x04eb877c) /* 0.307502256 */, 14 }, + /* 599 */ { MAD_F(0x04ee569d) /* 0.308188071 */, 14 }, + /* 600 */ { MAD_F(0x04f12624) /* 0.308874267 */, 14 }, + /* 601 */ { MAD_F(0x04f3f612) /* 0.309560845 */, 14 }, + /* 602 */ { MAD_F(0x04f6c666) /* 0.310247804 */, 14 }, + /* 603 */ { MAD_F(0x04f99721) /* 0.310935143 */, 14 }, + /* 604 */ { MAD_F(0x04fc6841) /* 0.311622862 */, 14 }, + /* 605 */ { MAD_F(0x04ff39c7) /* 0.312310961 */, 14 }, + /* 606 */ { MAD_F(0x05020bb3) /* 0.312999439 */, 14 }, + /* 607 */ { MAD_F(0x0504de05) /* 0.313688296 */, 14 }, + + /* 608 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 14 }, + /* 609 */ { MAD_F(0x050a83d8) /* 0.315067145 */, 14 }, + /* 610 */ { MAD_F(0x050d575b) /* 0.315757136 */, 14 }, + /* 611 */ { MAD_F(0x05102b42) /* 0.316447504 */, 14 }, + /* 612 */ { MAD_F(0x0512ff8e) /* 0.317138249 */, 14 }, + /* 613 */ { MAD_F(0x0515d440) /* 0.317829370 */, 14 }, + /* 614 */ { MAD_F(0x0518a956) /* 0.318520867 */, 14 }, + /* 615 */ { MAD_F(0x051b7ed1) /* 0.319212739 */, 14 }, + /* 616 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 14 }, + /* 617 */ { MAD_F(0x05212af5) /* 0.320597609 */, 14 }, + /* 618 */ { MAD_F(0x0524019e) /* 0.321290606 */, 14 }, + /* 619 */ { MAD_F(0x0526d8ab) /* 0.321983976 */, 14 }, + /* 620 */ { MAD_F(0x0529b01d) /* 0.322677720 */, 14 }, + /* 621 */ { MAD_F(0x052c87f2) /* 0.323371837 */, 14 }, + /* 622 */ { MAD_F(0x052f602c) /* 0.324066327 */, 14 }, + /* 623 */ { MAD_F(0x053238ca) /* 0.324761189 */, 14 }, + + /* 624 */ { MAD_F(0x053511cb) /* 0.325456423 */, 14 }, + /* 625 */ { MAD_F(0x0537eb30) /* 0.326152028 */, 14 }, + /* 626 */ { MAD_F(0x053ac4f9) /* 0.326848005 */, 14 }, + /* 627 */ { MAD_F(0x053d9f25) /* 0.327544352 */, 14 }, + /* 628 */ { MAD_F(0x054079b5) /* 0.328241070 */, 14 }, + /* 629 */ { MAD_F(0x054354a8) /* 0.328938157 */, 14 }, + /* 630 */ { MAD_F(0x05462ffe) /* 0.329635614 */, 14 }, + /* 631 */ { MAD_F(0x05490bb7) /* 0.330333440 */, 14 }, + /* 632 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 14 }, + /* 633 */ { MAD_F(0x054ec453) /* 0.331730198 */, 14 }, + /* 634 */ { MAD_F(0x0551a134) /* 0.332429129 */, 14 }, + /* 635 */ { MAD_F(0x05547e79) /* 0.333128427 */, 14 }, + /* 636 */ { MAD_F(0x05575c20) /* 0.333828093 */, 14 }, + /* 637 */ { MAD_F(0x055a3a2a) /* 0.334528126 */, 14 }, + /* 638 */ { MAD_F(0x055d1896) /* 0.335228525 */, 14 }, + /* 639 */ { MAD_F(0x055ff764) /* 0.335929290 */, 14 }, + + /* 640 */ { MAD_F(0x0562d694) /* 0.336630420 */, 14 }, + /* 641 */ { MAD_F(0x0565b627) /* 0.337331916 */, 14 }, + /* 642 */ { MAD_F(0x0568961b) /* 0.338033777 */, 14 }, + /* 643 */ { MAD_F(0x056b7671) /* 0.338736002 */, 14 }, + /* 644 */ { MAD_F(0x056e5729) /* 0.339438592 */, 14 }, + /* 645 */ { MAD_F(0x05713843) /* 0.340141545 */, 14 }, + /* 646 */ { MAD_F(0x057419be) /* 0.340844862 */, 14 }, + /* 647 */ { MAD_F(0x0576fb9a) /* 0.341548541 */, 14 }, + /* 648 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 14 }, + /* 649 */ { MAD_F(0x057cc077) /* 0.342956988 */, 14 }, + /* 650 */ { MAD_F(0x057fa378) /* 0.343661754 */, 14 }, + /* 651 */ { MAD_F(0x058286d9) /* 0.344366882 */, 14 }, + /* 652 */ { MAD_F(0x05856a9b) /* 0.345072371 */, 14 }, + /* 653 */ { MAD_F(0x05884ebe) /* 0.345778221 */, 14 }, + /* 654 */ { MAD_F(0x058b3342) /* 0.346484431 */, 14 }, + /* 655 */ { MAD_F(0x058e1827) /* 0.347191002 */, 14 }, + + /* 656 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 14 }, + /* 657 */ { MAD_F(0x0593e311) /* 0.348605221 */, 14 }, + /* 658 */ { MAD_F(0x0596c917) /* 0.349312869 */, 14 }, + /* 659 */ { MAD_F(0x0599af7d) /* 0.350020876 */, 14 }, + /* 660 */ { MAD_F(0x059c9643) /* 0.350729240 */, 14 }, + /* 661 */ { MAD_F(0x059f7d6a) /* 0.351437963 */, 14 }, + /* 662 */ { MAD_F(0x05a264f0) /* 0.352147044 */, 14 }, + /* 663 */ { MAD_F(0x05a54cd6) /* 0.352856481 */, 14 }, + /* 664 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 14 }, + /* 665 */ { MAD_F(0x05ab1dc2) /* 0.354276426 */, 14 }, + /* 666 */ { MAD_F(0x05ae06c7) /* 0.354986932 */, 14 }, + /* 667 */ { MAD_F(0x05b0f02b) /* 0.355697795 */, 14 }, + /* 668 */ { MAD_F(0x05b3d9f0) /* 0.356409012 */, 14 }, + /* 669 */ { MAD_F(0x05b6c413) /* 0.357120585 */, 14 }, + /* 670 */ { MAD_F(0x05b9ae95) /* 0.357832512 */, 14 }, + /* 671 */ { MAD_F(0x05bc9977) /* 0.358544794 */, 14 }, + + /* 672 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 14 }, + /* 673 */ { MAD_F(0x05c27057) /* 0.359970419 */, 14 }, + /* 674 */ { MAD_F(0x05c55c56) /* 0.360683761 */, 14 }, + /* 675 */ { MAD_F(0x05c848b3) /* 0.361397456 */, 14 }, + /* 676 */ { MAD_F(0x05cb356e) /* 0.362111504 */, 14 }, + /* 677 */ { MAD_F(0x05ce2289) /* 0.362825904 */, 14 }, + /* 678 */ { MAD_F(0x05d11001) /* 0.363540655 */, 14 }, + /* 679 */ { MAD_F(0x05d3fdd8) /* 0.364255759 */, 14 }, + /* 680 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 14 }, + /* 681 */ { MAD_F(0x05d9daa1) /* 0.365687018 */, 14 }, + /* 682 */ { MAD_F(0x05dcc993) /* 0.366403174 */, 14 }, + /* 683 */ { MAD_F(0x05dfb8e2) /* 0.367119680 */, 14 }, + /* 684 */ { MAD_F(0x05e2a890) /* 0.367836535 */, 14 }, + /* 685 */ { MAD_F(0x05e5989b) /* 0.368553740 */, 14 }, + /* 686 */ { MAD_F(0x05e88904) /* 0.369271294 */, 14 }, + /* 687 */ { MAD_F(0x05eb79cb) /* 0.369989197 */, 14 }, + + /* 688 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 14 }, + /* 689 */ { MAD_F(0x05f15c70) /* 0.371426047 */, 14 }, + /* 690 */ { MAD_F(0x05f44e4f) /* 0.372144994 */, 14 }, + /* 691 */ { MAD_F(0x05f7408b) /* 0.372864289 */, 14 }, + /* 692 */ { MAD_F(0x05fa3324) /* 0.373583930 */, 14 }, + /* 693 */ { MAD_F(0x05fd261b) /* 0.374303918 */, 14 }, + /* 694 */ { MAD_F(0x0600196e) /* 0.375024253 */, 14 }, + /* 695 */ { MAD_F(0x06030d1e) /* 0.375744934 */, 14 }, + /* 696 */ { MAD_F(0x0606012b) /* 0.376465960 */, 14 }, + /* 697 */ { MAD_F(0x0608f595) /* 0.377187332 */, 14 }, + /* 698 */ { MAD_F(0x060bea5c) /* 0.377909049 */, 14 }, + /* 699 */ { MAD_F(0x060edf7f) /* 0.378631110 */, 14 }, + /* 700 */ { MAD_F(0x0611d4fe) /* 0.379353516 */, 14 }, + /* 701 */ { MAD_F(0x0614cada) /* 0.380076266 */, 14 }, + /* 702 */ { MAD_F(0x0617c112) /* 0.380799360 */, 14 }, + /* 703 */ { MAD_F(0x061ab7a6) /* 0.381522798 */, 14 }, + + /* 704 */ { MAD_F(0x061dae96) /* 0.382246578 */, 14 }, + /* 705 */ { MAD_F(0x0620a5e3) /* 0.382970701 */, 14 }, + /* 706 */ { MAD_F(0x06239d8b) /* 0.383695167 */, 14 }, + /* 707 */ { MAD_F(0x0626958f) /* 0.384419975 */, 14 }, + /* 708 */ { MAD_F(0x06298def) /* 0.385145124 */, 14 }, + /* 709 */ { MAD_F(0x062c86aa) /* 0.385870615 */, 14 }, + /* 710 */ { MAD_F(0x062f7fc1) /* 0.386596448 */, 14 }, + /* 711 */ { MAD_F(0x06327934) /* 0.387322621 */, 14 }, + /* 712 */ { MAD_F(0x06357302) /* 0.388049134 */, 14 }, + /* 713 */ { MAD_F(0x06386d2b) /* 0.388775988 */, 14 }, + /* 714 */ { MAD_F(0x063b67b0) /* 0.389503182 */, 14 }, + /* 715 */ { MAD_F(0x063e6290) /* 0.390230715 */, 14 }, + /* 716 */ { MAD_F(0x06415dcb) /* 0.390958588 */, 14 }, + /* 717 */ { MAD_F(0x06445960) /* 0.391686799 */, 14 }, + /* 718 */ { MAD_F(0x06475551) /* 0.392415349 */, 14 }, + /* 719 */ { MAD_F(0x064a519c) /* 0.393144238 */, 14 }, + + /* 720 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 14 }, + /* 721 */ { MAD_F(0x06504b44) /* 0.394603028 */, 14 }, + /* 722 */ { MAD_F(0x0653489f) /* 0.395332930 */, 14 }, + /* 723 */ { MAD_F(0x06564655) /* 0.396063168 */, 14 }, + /* 724 */ { MAD_F(0x06594465) /* 0.396793743 */, 14 }, + /* 725 */ { MAD_F(0x065c42d0) /* 0.397524655 */, 14 }, + /* 726 */ { MAD_F(0x065f4195) /* 0.398255903 */, 14 }, + /* 727 */ { MAD_F(0x066240b4) /* 0.398987487 */, 14 }, + /* 728 */ { MAD_F(0x0665402d) /* 0.399719406 */, 14 }, + /* 729 */ { MAD_F(0x06684000) /* 0.400451660 */, 14 }, + /* 730 */ { MAD_F(0x066b402d) /* 0.401184249 */, 14 }, + /* 731 */ { MAD_F(0x066e40b3) /* 0.401917173 */, 14 }, + /* 732 */ { MAD_F(0x06714194) /* 0.402650431 */, 14 }, + /* 733 */ { MAD_F(0x067442ce) /* 0.403384024 */, 14 }, + /* 734 */ { MAD_F(0x06774462) /* 0.404117949 */, 14 }, + /* 735 */ { MAD_F(0x067a464f) /* 0.404852209 */, 14 }, + + /* 736 */ { MAD_F(0x067d4896) /* 0.405586801 */, 14 }, + /* 737 */ { MAD_F(0x06804b36) /* 0.406321726 */, 14 }, + /* 738 */ { MAD_F(0x06834e2f) /* 0.407056983 */, 14 }, + /* 739 */ { MAD_F(0x06865181) /* 0.407792573 */, 14 }, + /* 740 */ { MAD_F(0x0689552c) /* 0.408528495 */, 14 }, + /* 741 */ { MAD_F(0x068c5931) /* 0.409264748 */, 14 }, + /* 742 */ { MAD_F(0x068f5d8e) /* 0.410001332 */, 14 }, + /* 743 */ { MAD_F(0x06926245) /* 0.410738247 */, 14 }, + /* 744 */ { MAD_F(0x06956753) /* 0.411475493 */, 14 }, + /* 745 */ { MAD_F(0x06986cbb) /* 0.412213070 */, 14 }, + /* 746 */ { MAD_F(0x069b727b) /* 0.412950976 */, 14 }, + /* 747 */ { MAD_F(0x069e7894) /* 0.413689213 */, 14 }, + /* 748 */ { MAD_F(0x06a17f05) /* 0.414427779 */, 14 }, + /* 749 */ { MAD_F(0x06a485cf) /* 0.415166674 */, 14 }, + /* 750 */ { MAD_F(0x06a78cf1) /* 0.415905897 */, 14 }, + /* 751 */ { MAD_F(0x06aa946b) /* 0.416645450 */, 14 }, + + /* 752 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 14 }, + /* 753 */ { MAD_F(0x06b0a468) /* 0.418125540 */, 14 }, + /* 754 */ { MAD_F(0x06b3acea) /* 0.418866076 */, 14 }, + /* 755 */ { MAD_F(0x06b6b5c4) /* 0.419606940 */, 14 }, + /* 756 */ { MAD_F(0x06b9bef6) /* 0.420348132 */, 14 }, + /* 757 */ { MAD_F(0x06bcc880) /* 0.421089650 */, 14 }, + /* 758 */ { MAD_F(0x06bfd261) /* 0.421831494 */, 14 }, + /* 759 */ { MAD_F(0x06c2dc9a) /* 0.422573665 */, 14 }, + /* 760 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 14 }, + /* 761 */ { MAD_F(0x06c8f213) /* 0.424058985 */, 14 }, + /* 762 */ { MAD_F(0x06cbfd52) /* 0.424802133 */, 14 }, + /* 763 */ { MAD_F(0x06cf08e9) /* 0.425545607 */, 14 }, + /* 764 */ { MAD_F(0x06d214d7) /* 0.426289405 */, 14 }, + /* 765 */ { MAD_F(0x06d5211c) /* 0.427033528 */, 14 }, + /* 766 */ { MAD_F(0x06d82db8) /* 0.427777975 */, 14 }, + /* 767 */ { MAD_F(0x06db3aaa) /* 0.428522746 */, 14 }, + + /* 768 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 14 }, + /* 769 */ { MAD_F(0x06e15595) /* 0.430013259 */, 14 }, + /* 770 */ { MAD_F(0x06e4638d) /* 0.430759001 */, 14 }, + /* 771 */ { MAD_F(0x06e771db) /* 0.431505065 */, 14 }, + /* 772 */ { MAD_F(0x06ea807f) /* 0.432251452 */, 14 }, + /* 773 */ { MAD_F(0x06ed8f7b) /* 0.432998162 */, 14 }, + /* 774 */ { MAD_F(0x06f09ecc) /* 0.433745193 */, 14 }, + /* 775 */ { MAD_F(0x06f3ae75) /* 0.434492546 */, 14 }, + /* 776 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 14 }, + /* 777 */ { MAD_F(0x06f9cec8) /* 0.435988217 */, 14 }, + /* 778 */ { MAD_F(0x06fcdf72) /* 0.436736534 */, 14 }, + /* 779 */ { MAD_F(0x06fff073) /* 0.437485172 */, 14 }, + /* 780 */ { MAD_F(0x070301ca) /* 0.438234130 */, 14 }, + /* 781 */ { MAD_F(0x07061377) /* 0.438983408 */, 14 }, + /* 782 */ { MAD_F(0x0709257a) /* 0.439733006 */, 14 }, + /* 783 */ { MAD_F(0x070c37d2) /* 0.440482924 */, 14 }, + + /* 784 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 14 }, + /* 785 */ { MAD_F(0x07125d84) /* 0.441983717 */, 14 }, + /* 786 */ { MAD_F(0x071570de) /* 0.442734592 */, 14 }, + /* 787 */ { MAD_F(0x0718848d) /* 0.443485785 */, 14 }, + /* 788 */ { MAD_F(0x071b9891) /* 0.444237296 */, 14 }, + /* 789 */ { MAD_F(0x071eaceb) /* 0.444989126 */, 14 }, + /* 790 */ { MAD_F(0x0721c19a) /* 0.445741273 */, 14 }, + /* 791 */ { MAD_F(0x0724d69e) /* 0.446493738 */, 14 }, + /* 792 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 14 }, + /* 793 */ { MAD_F(0x072b01a6) /* 0.447999618 */, 14 }, + /* 794 */ { MAD_F(0x072e17a9) /* 0.448753033 */, 14 }, + /* 795 */ { MAD_F(0x07312e01) /* 0.449506765 */, 14 }, + /* 796 */ { MAD_F(0x073444ae) /* 0.450260813 */, 14 }, + /* 797 */ { MAD_F(0x07375bb0) /* 0.451015176 */, 14 }, + /* 798 */ { MAD_F(0x073a7307) /* 0.451769856 */, 14 }, + /* 799 */ { MAD_F(0x073d8ab2) /* 0.452524850 */, 14 }, + + /* 800 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 14 }, + /* 801 */ { MAD_F(0x0743bb06) /* 0.454035784 */, 14 }, + /* 802 */ { MAD_F(0x0746d3af) /* 0.454791723 */, 14 }, + /* 803 */ { MAD_F(0x0749ecac) /* 0.455547976 */, 14 }, + /* 804 */ { MAD_F(0x074d05fe) /* 0.456304543 */, 14 }, + /* 805 */ { MAD_F(0x07501fa3) /* 0.457061423 */, 14 }, + /* 806 */ { MAD_F(0x0753399d) /* 0.457818618 */, 14 }, + /* 807 */ { MAD_F(0x075653eb) /* 0.458576125 */, 14 }, + /* 808 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 14 }, + /* 809 */ { MAD_F(0x075c8983) /* 0.460092079 */, 14 }, + /* 810 */ { MAD_F(0x075fa4cc) /* 0.460850524 */, 14 }, + /* 811 */ { MAD_F(0x0762c06a) /* 0.461609282 */, 14 }, + /* 812 */ { MAD_F(0x0765dc5b) /* 0.462368352 */, 14 }, + /* 813 */ { MAD_F(0x0768f8a0) /* 0.463127733 */, 14 }, + /* 814 */ { MAD_F(0x076c1538) /* 0.463887426 */, 14 }, + /* 815 */ { MAD_F(0x076f3224) /* 0.464647430 */, 14 }, + + /* 816 */ { MAD_F(0x07724f64) /* 0.465407744 */, 14 }, + /* 817 */ { MAD_F(0x07756cf7) /* 0.466168370 */, 14 }, + /* 818 */ { MAD_F(0x07788add) /* 0.466929306 */, 14 }, + /* 819 */ { MAD_F(0x077ba916) /* 0.467690552 */, 14 }, + /* 820 */ { MAD_F(0x077ec7a3) /* 0.468452108 */, 14 }, + /* 821 */ { MAD_F(0x0781e683) /* 0.469213973 */, 14 }, + /* 822 */ { MAD_F(0x078505b5) /* 0.469976148 */, 14 }, + /* 823 */ { MAD_F(0x0788253b) /* 0.470738632 */, 14 }, + /* 824 */ { MAD_F(0x078b4514) /* 0.471501425 */, 14 }, + /* 825 */ { MAD_F(0x078e653f) /* 0.472264527 */, 14 }, + /* 826 */ { MAD_F(0x079185be) /* 0.473027937 */, 14 }, + /* 827 */ { MAD_F(0x0794a68f) /* 0.473791655 */, 14 }, + /* 828 */ { MAD_F(0x0797c7b2) /* 0.474555681 */, 14 }, + /* 829 */ { MAD_F(0x079ae929) /* 0.475320014 */, 14 }, + /* 830 */ { MAD_F(0x079e0af1) /* 0.476084655 */, 14 }, + /* 831 */ { MAD_F(0x07a12d0c) /* 0.476849603 */, 14 }, + + /* 832 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 14 }, + /* 833 */ { MAD_F(0x07a7723a) /* 0.478380420 */, 14 }, + /* 834 */ { MAD_F(0x07aa954c) /* 0.479146288 */, 14 }, + /* 835 */ { MAD_F(0x07adb8b0) /* 0.479912463 */, 14 }, + /* 836 */ { MAD_F(0x07b0dc67) /* 0.480678943 */, 14 }, + /* 837 */ { MAD_F(0x07b4006f) /* 0.481445729 */, 14 }, + /* 838 */ { MAD_F(0x07b724ca) /* 0.482212820 */, 14 }, + /* 839 */ { MAD_F(0x07ba4976) /* 0.482980216 */, 14 }, + /* 840 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 14 }, + /* 841 */ { MAD_F(0x07c093c5) /* 0.484515924 */, 14 }, + /* 842 */ { MAD_F(0x07c3b967) /* 0.485284235 */, 14 }, + /* 843 */ { MAD_F(0x07c6df5a) /* 0.486052849 */, 14 }, + /* 844 */ { MAD_F(0x07ca059f) /* 0.486821768 */, 14 }, + /* 845 */ { MAD_F(0x07cd2c36) /* 0.487590991 */, 14 }, + /* 846 */ { MAD_F(0x07d0531e) /* 0.488360517 */, 14 }, + /* 847 */ { MAD_F(0x07d37a57) /* 0.489130346 */, 14 }, + + /* 848 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 14 }, + /* 849 */ { MAD_F(0x07d9c9be) /* 0.490670914 */, 14 }, + /* 850 */ { MAD_F(0x07dcf1ec) /* 0.491441651 */, 14 }, + /* 851 */ { MAD_F(0x07e01a6a) /* 0.492212691 */, 14 }, + /* 852 */ { MAD_F(0x07e3433a) /* 0.492984033 */, 14 }, + /* 853 */ { MAD_F(0x07e66c5a) /* 0.493755677 */, 14 }, + /* 854 */ { MAD_F(0x07e995cc) /* 0.494527623 */, 14 }, + /* 855 */ { MAD_F(0x07ecbf8e) /* 0.495299870 */, 14 }, + /* 856 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 14 }, + /* 857 */ { MAD_F(0x07f31405) /* 0.496845266 */, 14 }, + /* 858 */ { MAD_F(0x07f63eba) /* 0.497618416 */, 14 }, + /* 859 */ { MAD_F(0x07f969c0) /* 0.498391866 */, 14 }, + /* 860 */ { MAD_F(0x07fc9516) /* 0.499165616 */, 14 }, + /* 861 */ { MAD_F(0x07ffc0bc) /* 0.499939666 */, 14 }, + /* 862 */ { MAD_F(0x04017659) /* 0.250357008 */, 15 }, + /* 863 */ { MAD_F(0x04030c7d) /* 0.250744333 */, 15 }, + + /* 864 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 15 }, + /* 865 */ { MAD_F(0x0406393d) /* 0.251519431 */, 15 }, + /* 866 */ { MAD_F(0x0407cfd9) /* 0.251907204 */, 15 }, + /* 867 */ { MAD_F(0x0409669d) /* 0.252295127 */, 15 }, + /* 868 */ { MAD_F(0x040afd89) /* 0.252683198 */, 15 }, + /* 869 */ { MAD_F(0x040c949e) /* 0.253071419 */, 15 }, + /* 870 */ { MAD_F(0x040e2bda) /* 0.253459789 */, 15 }, + /* 871 */ { MAD_F(0x040fc33e) /* 0.253848307 */, 15 }, + /* 872 */ { MAD_F(0x04115aca) /* 0.254236974 */, 15 }, + /* 873 */ { MAD_F(0x0412f27e) /* 0.254625790 */, 15 }, + /* 874 */ { MAD_F(0x04148a5a) /* 0.255014755 */, 15 }, + /* 875 */ { MAD_F(0x0416225d) /* 0.255403867 */, 15 }, + /* 876 */ { MAD_F(0x0417ba89) /* 0.255793128 */, 15 }, + /* 877 */ { MAD_F(0x041952dc) /* 0.256182537 */, 15 }, + /* 878 */ { MAD_F(0x041aeb57) /* 0.256572095 */, 15 }, + /* 879 */ { MAD_F(0x041c83fa) /* 0.256961800 */, 15 }, + + /* 880 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 15 }, + /* 881 */ { MAD_F(0x041fb5b6) /* 0.257741653 */, 15 }, + /* 882 */ { MAD_F(0x04214ed0) /* 0.258131801 */, 15 }, + /* 883 */ { MAD_F(0x0422e811) /* 0.258522097 */, 15 }, + /* 884 */ { MAD_F(0x04248179) /* 0.258912540 */, 15 }, + /* 885 */ { MAD_F(0x04261b0a) /* 0.259303130 */, 15 }, + /* 886 */ { MAD_F(0x0427b4c2) /* 0.259693868 */, 15 }, + /* 887 */ { MAD_F(0x04294ea1) /* 0.260084752 */, 15 }, + /* 888 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 15 }, + /* 889 */ { MAD_F(0x042c82d6) /* 0.260866961 */, 15 }, + /* 890 */ { MAD_F(0x042e1d2b) /* 0.261258286 */, 15 }, + /* 891 */ { MAD_F(0x042fb7a8) /* 0.261649758 */, 15 }, + /* 892 */ { MAD_F(0x0431524c) /* 0.262041376 */, 15 }, + /* 893 */ { MAD_F(0x0432ed17) /* 0.262433140 */, 15 }, + /* 894 */ { MAD_F(0x0434880a) /* 0.262825051 */, 15 }, + /* 895 */ { MAD_F(0x04362324) /* 0.263217107 */, 15 }, + + /* 896 */ { MAD_F(0x0437be65) /* 0.263609310 */, 15 }, + /* 897 */ { MAD_F(0x043959cd) /* 0.264001659 */, 15 }, + /* 898 */ { MAD_F(0x043af55d) /* 0.264394153 */, 15 }, + /* 899 */ { MAD_F(0x043c9113) /* 0.264786794 */, 15 }, + /* 900 */ { MAD_F(0x043e2cf1) /* 0.265179580 */, 15 }, + /* 901 */ { MAD_F(0x043fc8f6) /* 0.265572511 */, 15 }, + /* 902 */ { MAD_F(0x04416522) /* 0.265965588 */, 15 }, + /* 903 */ { MAD_F(0x04430174) /* 0.266358810 */, 15 }, + /* 904 */ { MAD_F(0x04449dee) /* 0.266752177 */, 15 }, + /* 905 */ { MAD_F(0x04463a8f) /* 0.267145689 */, 15 }, + /* 906 */ { MAD_F(0x0447d756) /* 0.267539347 */, 15 }, + /* 907 */ { MAD_F(0x04497445) /* 0.267933149 */, 15 }, + /* 908 */ { MAD_F(0x044b115a) /* 0.268327096 */, 15 }, + /* 909 */ { MAD_F(0x044cae96) /* 0.268721187 */, 15 }, + /* 910 */ { MAD_F(0x044e4bf9) /* 0.269115423 */, 15 }, + /* 911 */ { MAD_F(0x044fe983) /* 0.269509804 */, 15 }, + + /* 912 */ { MAD_F(0x04518733) /* 0.269904329 */, 15 }, + /* 913 */ { MAD_F(0x0453250a) /* 0.270298998 */, 15 }, + /* 914 */ { MAD_F(0x0454c308) /* 0.270693811 */, 15 }, + /* 915 */ { MAD_F(0x0456612d) /* 0.271088768 */, 15 }, + /* 916 */ { MAD_F(0x0457ff78) /* 0.271483869 */, 15 }, + /* 917 */ { MAD_F(0x04599dea) /* 0.271879114 */, 15 }, + /* 918 */ { MAD_F(0x045b3c82) /* 0.272274503 */, 15 }, + /* 919 */ { MAD_F(0x045cdb41) /* 0.272670035 */, 15 }, + /* 920 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 15 }, + /* 921 */ { MAD_F(0x04601932) /* 0.273461530 */, 15 }, + /* 922 */ { MAD_F(0x0461b864) /* 0.273857492 */, 15 }, + /* 923 */ { MAD_F(0x046357bd) /* 0.274253597 */, 15 }, + /* 924 */ { MAD_F(0x0464f73c) /* 0.274649846 */, 15 }, + /* 925 */ { MAD_F(0x046696e2) /* 0.275046238 */, 15 }, + /* 926 */ { MAD_F(0x046836ae) /* 0.275442772 */, 15 }, + /* 927 */ { MAD_F(0x0469d6a0) /* 0.275839449 */, 15 }, + + /* 928 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 15 }, + /* 929 */ { MAD_F(0x046d16f7) /* 0.276633232 */, 15 }, + /* 930 */ { MAD_F(0x046eb75c) /* 0.277030337 */, 15 }, + /* 931 */ { MAD_F(0x047057e8) /* 0.277427584 */, 15 }, + /* 932 */ { MAD_F(0x0471f899) /* 0.277824973 */, 15 }, + /* 933 */ { MAD_F(0x04739971) /* 0.278222505 */, 15 }, + /* 934 */ { MAD_F(0x04753a6f) /* 0.278620179 */, 15 }, + /* 935 */ { MAD_F(0x0476db92) /* 0.279017995 */, 15 }, + /* 936 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 15 }, + /* 937 */ { MAD_F(0x047a1e4c) /* 0.279814051 */, 15 }, + /* 938 */ { MAD_F(0x047bbfe2) /* 0.280212292 */, 15 }, + /* 939 */ { MAD_F(0x047d619e) /* 0.280610675 */, 15 }, + /* 940 */ { MAD_F(0x047f0380) /* 0.281009199 */, 15 }, + /* 941 */ { MAD_F(0x0480a588) /* 0.281407864 */, 15 }, + /* 942 */ { MAD_F(0x048247b6) /* 0.281806670 */, 15 }, + /* 943 */ { MAD_F(0x0483ea0a) /* 0.282205618 */, 15 }, + + /* 944 */ { MAD_F(0x04858c83) /* 0.282604707 */, 15 }, + /* 945 */ { MAD_F(0x04872f22) /* 0.283003936 */, 15 }, + /* 946 */ { MAD_F(0x0488d1e8) /* 0.283403307 */, 15 }, + /* 947 */ { MAD_F(0x048a74d3) /* 0.283802818 */, 15 }, + /* 948 */ { MAD_F(0x048c17e3) /* 0.284202470 */, 15 }, + /* 949 */ { MAD_F(0x048dbb1a) /* 0.284602263 */, 15 }, + /* 950 */ { MAD_F(0x048f5e76) /* 0.285002195 */, 15 }, + /* 951 */ { MAD_F(0x049101f8) /* 0.285402269 */, 15 }, + /* 952 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 15 }, + /* 953 */ { MAD_F(0x0494496c) /* 0.286202836 */, 15 }, + /* 954 */ { MAD_F(0x0495ed5f) /* 0.286603329 */, 15 }, + /* 955 */ { MAD_F(0x04979177) /* 0.287003963 */, 15 }, + /* 956 */ { MAD_F(0x049935b5) /* 0.287404737 */, 15 }, + /* 957 */ { MAD_F(0x049ada19) /* 0.287805650 */, 15 }, + /* 958 */ { MAD_F(0x049c7ea1) /* 0.288206703 */, 15 }, + /* 959 */ { MAD_F(0x049e2350) /* 0.288607895 */, 15 }, + + /* 960 */ { MAD_F(0x049fc824) /* 0.289009227 */, 15 }, + /* 961 */ { MAD_F(0x04a16d1d) /* 0.289410699 */, 15 }, + /* 962 */ { MAD_F(0x04a3123b) /* 0.289812309 */, 15 }, + /* 963 */ { MAD_F(0x04a4b77f) /* 0.290214059 */, 15 }, + /* 964 */ { MAD_F(0x04a65ce8) /* 0.290615948 */, 15 }, + /* 965 */ { MAD_F(0x04a80277) /* 0.291017976 */, 15 }, + /* 966 */ { MAD_F(0x04a9a82b) /* 0.291420143 */, 15 }, + /* 967 */ { MAD_F(0x04ab4e04) /* 0.291822449 */, 15 }, + /* 968 */ { MAD_F(0x04acf402) /* 0.292224893 */, 15 }, + /* 969 */ { MAD_F(0x04ae9a26) /* 0.292627476 */, 15 }, + /* 970 */ { MAD_F(0x04b0406e) /* 0.293030197 */, 15 }, + /* 971 */ { MAD_F(0x04b1e6dc) /* 0.293433057 */, 15 }, + /* 972 */ { MAD_F(0x04b38d6f) /* 0.293836055 */, 15 }, + /* 973 */ { MAD_F(0x04b53427) /* 0.294239192 */, 15 }, + /* 974 */ { MAD_F(0x04b6db05) /* 0.294642466 */, 15 }, + /* 975 */ { MAD_F(0x04b88207) /* 0.295045879 */, 15 }, + + /* 976 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 15 }, + /* 977 */ { MAD_F(0x04bbd07a) /* 0.295853118 */, 15 }, + /* 978 */ { MAD_F(0x04bd77ec) /* 0.296256944 */, 15 }, + /* 979 */ { MAD_F(0x04bf1f82) /* 0.296660907 */, 15 }, + /* 980 */ { MAD_F(0x04c0c73d) /* 0.297065009 */, 15 }, + /* 981 */ { MAD_F(0x04c26f1d) /* 0.297469248 */, 15 }, + /* 982 */ { MAD_F(0x04c41722) /* 0.297873624 */, 15 }, + /* 983 */ { MAD_F(0x04c5bf4c) /* 0.298278137 */, 15 }, + /* 984 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 15 }, + /* 985 */ { MAD_F(0x04c9100d) /* 0.299087576 */, 15 }, + /* 986 */ { MAD_F(0x04cab8a6) /* 0.299492500 */, 15 }, + /* 987 */ { MAD_F(0x04cc6163) /* 0.299897562 */, 15 }, + /* 988 */ { MAD_F(0x04ce0a44) /* 0.300302761 */, 15 }, + /* 989 */ { MAD_F(0x04cfb34b) /* 0.300708096 */, 15 }, + /* 990 */ { MAD_F(0x04d15c76) /* 0.301113568 */, 15 }, + /* 991 */ { MAD_F(0x04d305c5) /* 0.301519176 */, 15 }, + + /* 992 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 15 }, + /* 993 */ { MAD_F(0x04d658d2) /* 0.302330802 */, 15 }, + /* 994 */ { MAD_F(0x04d80290) /* 0.302736820 */, 15 }, + /* 995 */ { MAD_F(0x04d9ac72) /* 0.303142973 */, 15 }, + /* 996 */ { MAD_F(0x04db5679) /* 0.303549263 */, 15 }, + /* 997 */ { MAD_F(0x04dd00a4) /* 0.303955689 */, 15 }, + /* 998 */ { MAD_F(0x04deaaf3) /* 0.304362251 */, 15 }, + /* 999 */ { MAD_F(0x04e05567) /* 0.304768948 */, 15 }, + /* 1000 */ { MAD_F(0x04e20000) /* 0.305175781 */, 15 }, + /* 1001 */ { MAD_F(0x04e3aabd) /* 0.305582750 */, 15 }, + /* 1002 */ { MAD_F(0x04e5559e) /* 0.305989854 */, 15 }, + /* 1003 */ { MAD_F(0x04e700a3) /* 0.306397094 */, 15 }, + /* 1004 */ { MAD_F(0x04e8abcd) /* 0.306804470 */, 15 }, + /* 1005 */ { MAD_F(0x04ea571c) /* 0.307211980 */, 15 }, + /* 1006 */ { MAD_F(0x04ec028e) /* 0.307619626 */, 15 }, + /* 1007 */ { MAD_F(0x04edae25) /* 0.308027406 */, 15 }, + + /* 1008 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 15 }, + /* 1009 */ { MAD_F(0x04f105bf) /* 0.308843373 */, 15 }, + /* 1010 */ { MAD_F(0x04f2b1c3) /* 0.309251558 */, 15 }, + /* 1011 */ { MAD_F(0x04f45dea) /* 0.309659879 */, 15 }, + /* 1012 */ { MAD_F(0x04f60a36) /* 0.310068333 */, 15 }, + /* 1013 */ { MAD_F(0x04f7b6a6) /* 0.310476923 */, 15 }, + /* 1014 */ { MAD_F(0x04f9633a) /* 0.310885647 */, 15 }, + /* 1015 */ { MAD_F(0x04fb0ff2) /* 0.311294505 */, 15 }, + /* 1016 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 15 }, + /* 1017 */ { MAD_F(0x04fe69ce) /* 0.312112625 */, 15 }, + /* 1018 */ { MAD_F(0x050016f3) /* 0.312521885 */, 15 }, + /* 1019 */ { MAD_F(0x0501c43b) /* 0.312931280 */, 15 }, + /* 1020 */ { MAD_F(0x050371a7) /* 0.313340809 */, 15 }, + /* 1021 */ { MAD_F(0x05051f37) /* 0.313750472 */, 15 }, + /* 1022 */ { MAD_F(0x0506cceb) /* 0.314160269 */, 15 }, + /* 1023 */ { MAD_F(0x05087ac2) /* 0.314570199 */, 15 }, + + /* 1024 */ { MAD_F(0x050a28be) /* 0.314980262 */, 15 }, + /* 1025 */ { MAD_F(0x050bd6de) /* 0.315390460 */, 15 }, + /* 1026 */ { MAD_F(0x050d8521) /* 0.315800790 */, 15 }, + /* 1027 */ { MAD_F(0x050f3388) /* 0.316211255 */, 15 }, + /* 1028 */ { MAD_F(0x0510e213) /* 0.316621852 */, 15 }, + /* 1029 */ { MAD_F(0x051290c2) /* 0.317032582 */, 15 }, + /* 1030 */ { MAD_F(0x05143f94) /* 0.317443446 */, 15 }, + /* 1031 */ { MAD_F(0x0515ee8a) /* 0.317854442 */, 15 }, + /* 1032 */ { MAD_F(0x05179da4) /* 0.318265572 */, 15 }, + /* 1033 */ { MAD_F(0x05194ce1) /* 0.318676834 */, 15 }, + /* 1034 */ { MAD_F(0x051afc42) /* 0.319088229 */, 15 }, + /* 1035 */ { MAD_F(0x051cabc7) /* 0.319499756 */, 15 }, + /* 1036 */ { MAD_F(0x051e5b6f) /* 0.319911417 */, 15 }, + /* 1037 */ { MAD_F(0x05200b3a) /* 0.320323209 */, 15 }, + /* 1038 */ { MAD_F(0x0521bb2a) /* 0.320735134 */, 15 }, + /* 1039 */ { MAD_F(0x05236b3d) /* 0.321147192 */, 15 }, + + /* 1040 */ { MAD_F(0x05251b73) /* 0.321559381 */, 15 }, + /* 1041 */ { MAD_F(0x0526cbcd) /* 0.321971703 */, 15 }, + /* 1042 */ { MAD_F(0x05287c4a) /* 0.322384156 */, 15 }, + /* 1043 */ { MAD_F(0x052a2cea) /* 0.322796742 */, 15 }, + /* 1044 */ { MAD_F(0x052bddae) /* 0.323209460 */, 15 }, + /* 1045 */ { MAD_F(0x052d8e96) /* 0.323622309 */, 15 }, + /* 1046 */ { MAD_F(0x052f3fa1) /* 0.324035290 */, 15 }, + /* 1047 */ { MAD_F(0x0530f0cf) /* 0.324448403 */, 15 }, + /* 1048 */ { MAD_F(0x0532a220) /* 0.324861647 */, 15 }, + /* 1049 */ { MAD_F(0x05345395) /* 0.325275023 */, 15 }, + /* 1050 */ { MAD_F(0x0536052d) /* 0.325688530 */, 15 }, + /* 1051 */ { MAD_F(0x0537b6e8) /* 0.326102168 */, 15 }, + /* 1052 */ { MAD_F(0x053968c6) /* 0.326515938 */, 15 }, + /* 1053 */ { MAD_F(0x053b1ac8) /* 0.326929839 */, 15 }, + /* 1054 */ { MAD_F(0x053ccced) /* 0.327343870 */, 15 }, + /* 1055 */ { MAD_F(0x053e7f35) /* 0.327758033 */, 15 }, + + /* 1056 */ { MAD_F(0x054031a0) /* 0.328172327 */, 15 }, + /* 1057 */ { MAD_F(0x0541e42e) /* 0.328586751 */, 15 }, + /* 1058 */ { MAD_F(0x054396df) /* 0.329001306 */, 15 }, + /* 1059 */ { MAD_F(0x054549b4) /* 0.329415992 */, 15 }, + /* 1060 */ { MAD_F(0x0546fcab) /* 0.329830808 */, 15 }, + /* 1061 */ { MAD_F(0x0548afc6) /* 0.330245755 */, 15 }, + /* 1062 */ { MAD_F(0x054a6303) /* 0.330660832 */, 15 }, + /* 1063 */ { MAD_F(0x054c1663) /* 0.331076039 */, 15 }, + /* 1064 */ { MAD_F(0x054dc9e7) /* 0.331491377 */, 15 }, + /* 1065 */ { MAD_F(0x054f7d8d) /* 0.331906845 */, 15 }, + /* 1066 */ { MAD_F(0x05513156) /* 0.332322443 */, 15 }, + /* 1067 */ { MAD_F(0x0552e542) /* 0.332738170 */, 15 }, + /* 1068 */ { MAD_F(0x05549951) /* 0.333154028 */, 15 }, + /* 1069 */ { MAD_F(0x05564d83) /* 0.333570016 */, 15 }, + /* 1070 */ { MAD_F(0x055801d8) /* 0.333986133 */, 15 }, + /* 1071 */ { MAD_F(0x0559b64f) /* 0.334402380 */, 15 }, + + /* 1072 */ { MAD_F(0x055b6ae9) /* 0.334818756 */, 15 }, + /* 1073 */ { MAD_F(0x055d1fa6) /* 0.335235262 */, 15 }, + /* 1074 */ { MAD_F(0x055ed486) /* 0.335651898 */, 15 }, + /* 1075 */ { MAD_F(0x05608988) /* 0.336068662 */, 15 }, + /* 1076 */ { MAD_F(0x05623ead) /* 0.336485556 */, 15 }, + /* 1077 */ { MAD_F(0x0563f3f5) /* 0.336902579 */, 15 }, + /* 1078 */ { MAD_F(0x0565a960) /* 0.337319732 */, 15 }, + /* 1079 */ { MAD_F(0x05675eed) /* 0.337737013 */, 15 }, + /* 1080 */ { MAD_F(0x0569149c) /* 0.338154423 */, 15 }, + /* 1081 */ { MAD_F(0x056aca6f) /* 0.338571962 */, 15 }, + /* 1082 */ { MAD_F(0x056c8064) /* 0.338989630 */, 15 }, + /* 1083 */ { MAD_F(0x056e367b) /* 0.339407426 */, 15 }, + /* 1084 */ { MAD_F(0x056fecb5) /* 0.339825351 */, 15 }, + /* 1085 */ { MAD_F(0x0571a311) /* 0.340243405 */, 15 }, + /* 1086 */ { MAD_F(0x05735990) /* 0.340661587 */, 15 }, + /* 1087 */ { MAD_F(0x05751032) /* 0.341079898 */, 15 }, + + /* 1088 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 15 }, + /* 1089 */ { MAD_F(0x05787ddc) /* 0.341916903 */, 15 }, + /* 1090 */ { MAD_F(0x057a34e4) /* 0.342335598 */, 15 }, + /* 1091 */ { MAD_F(0x057bec0f) /* 0.342754421 */, 15 }, + /* 1092 */ { MAD_F(0x057da35d) /* 0.343173373 */, 15 }, + /* 1093 */ { MAD_F(0x057f5acc) /* 0.343592452 */, 15 }, + /* 1094 */ { MAD_F(0x0581125e) /* 0.344011659 */, 15 }, + /* 1095 */ { MAD_F(0x0582ca12) /* 0.344430993 */, 15 }, + /* 1096 */ { MAD_F(0x058481e9) /* 0.344850455 */, 15 }, + /* 1097 */ { MAD_F(0x058639e2) /* 0.345270045 */, 15 }, + /* 1098 */ { MAD_F(0x0587f1fd) /* 0.345689763 */, 15 }, + /* 1099 */ { MAD_F(0x0589aa3a) /* 0.346109608 */, 15 }, + /* 1100 */ { MAD_F(0x058b629a) /* 0.346529580 */, 15 }, + /* 1101 */ { MAD_F(0x058d1b1b) /* 0.346949679 */, 15 }, + /* 1102 */ { MAD_F(0x058ed3bf) /* 0.347369906 */, 15 }, + /* 1103 */ { MAD_F(0x05908c85) /* 0.347790260 */, 15 }, + + /* 1104 */ { MAD_F(0x0592456d) /* 0.348210741 */, 15 }, + /* 1105 */ { MAD_F(0x0593fe77) /* 0.348631348 */, 15 }, + /* 1106 */ { MAD_F(0x0595b7a3) /* 0.349052083 */, 15 }, + /* 1107 */ { MAD_F(0x059770f1) /* 0.349472945 */, 15 }, + /* 1108 */ { MAD_F(0x05992a61) /* 0.349893933 */, 15 }, + /* 1109 */ { MAD_F(0x059ae3f3) /* 0.350315048 */, 15 }, + /* 1110 */ { MAD_F(0x059c9da8) /* 0.350736290 */, 15 }, + /* 1111 */ { MAD_F(0x059e577e) /* 0.351157658 */, 15 }, + /* 1112 */ { MAD_F(0x05a01176) /* 0.351579152 */, 15 }, + /* 1113 */ { MAD_F(0x05a1cb90) /* 0.352000773 */, 15 }, + /* 1114 */ { MAD_F(0x05a385cc) /* 0.352422520 */, 15 }, + /* 1115 */ { MAD_F(0x05a5402a) /* 0.352844394 */, 15 }, + /* 1116 */ { MAD_F(0x05a6faa9) /* 0.353266393 */, 15 }, + /* 1117 */ { MAD_F(0x05a8b54b) /* 0.353688519 */, 15 }, + /* 1118 */ { MAD_F(0x05aa700e) /* 0.354110771 */, 15 }, + /* 1119 */ { MAD_F(0x05ac2af3) /* 0.354533148 */, 15 }, + + /* 1120 */ { MAD_F(0x05ade5fa) /* 0.354955651 */, 15 }, + /* 1121 */ { MAD_F(0x05afa123) /* 0.355378281 */, 15 }, + /* 1122 */ { MAD_F(0x05b15c6d) /* 0.355801035 */, 15 }, + /* 1123 */ { MAD_F(0x05b317d9) /* 0.356223916 */, 15 }, + /* 1124 */ { MAD_F(0x05b4d367) /* 0.356646922 */, 15 }, + /* 1125 */ { MAD_F(0x05b68f16) /* 0.357070053 */, 15 }, + /* 1126 */ { MAD_F(0x05b84ae7) /* 0.357493310 */, 15 }, + /* 1127 */ { MAD_F(0x05ba06da) /* 0.357916692 */, 15 }, + /* 1128 */ { MAD_F(0x05bbc2ef) /* 0.358340200 */, 15 }, + /* 1129 */ { MAD_F(0x05bd7f25) /* 0.358763832 */, 15 }, + /* 1130 */ { MAD_F(0x05bf3b7c) /* 0.359187590 */, 15 }, + /* 1131 */ { MAD_F(0x05c0f7f5) /* 0.359611472 */, 15 }, + /* 1132 */ { MAD_F(0x05c2b490) /* 0.360035480 */, 15 }, + /* 1133 */ { MAD_F(0x05c4714c) /* 0.360459613 */, 15 }, + /* 1134 */ { MAD_F(0x05c62e2a) /* 0.360883870 */, 15 }, + /* 1135 */ { MAD_F(0x05c7eb29) /* 0.361308252 */, 15 }, + + /* 1136 */ { MAD_F(0x05c9a84a) /* 0.361732758 */, 15 }, + /* 1137 */ { MAD_F(0x05cb658c) /* 0.362157390 */, 15 }, + /* 1138 */ { MAD_F(0x05cd22ef) /* 0.362582145 */, 15 }, + /* 1139 */ { MAD_F(0x05cee074) /* 0.363007026 */, 15 }, + /* 1140 */ { MAD_F(0x05d09e1b) /* 0.363432030 */, 15 }, + /* 1141 */ { MAD_F(0x05d25be2) /* 0.363857159 */, 15 }, + /* 1142 */ { MAD_F(0x05d419cb) /* 0.364282412 */, 15 }, + /* 1143 */ { MAD_F(0x05d5d7d5) /* 0.364707789 */, 15 }, + /* 1144 */ { MAD_F(0x05d79601) /* 0.365133291 */, 15 }, + /* 1145 */ { MAD_F(0x05d9544e) /* 0.365558916 */, 15 }, + /* 1146 */ { MAD_F(0x05db12bc) /* 0.365984665 */, 15 }, + /* 1147 */ { MAD_F(0x05dcd14c) /* 0.366410538 */, 15 }, + /* 1148 */ { MAD_F(0x05de8ffc) /* 0.366836535 */, 15 }, + /* 1149 */ { MAD_F(0x05e04ece) /* 0.367262655 */, 15 }, + /* 1150 */ { MAD_F(0x05e20dc1) /* 0.367688900 */, 15 }, + /* 1151 */ { MAD_F(0x05e3ccd5) /* 0.368115267 */, 15 }, + + /* 1152 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 15 }, + /* 1153 */ { MAD_F(0x05e74b61) /* 0.368968373 */, 15 }, + /* 1154 */ { MAD_F(0x05e90ad9) /* 0.369395111 */, 15 }, + /* 1155 */ { MAD_F(0x05eaca72) /* 0.369821973 */, 15 }, + /* 1156 */ { MAD_F(0x05ec8a2b) /* 0.370248957 */, 15 }, + /* 1157 */ { MAD_F(0x05ee4a06) /* 0.370676065 */, 15 }, + /* 1158 */ { MAD_F(0x05f00a02) /* 0.371103295 */, 15 }, + /* 1159 */ { MAD_F(0x05f1ca1f) /* 0.371530649 */, 15 }, + /* 1160 */ { MAD_F(0x05f38a5d) /* 0.371958126 */, 15 }, + /* 1161 */ { MAD_F(0x05f54abc) /* 0.372385725 */, 15 }, + /* 1162 */ { MAD_F(0x05f70b3c) /* 0.372813448 */, 15 }, + /* 1163 */ { MAD_F(0x05f8cbdc) /* 0.373241292 */, 15 }, + /* 1164 */ { MAD_F(0x05fa8c9e) /* 0.373669260 */, 15 }, + /* 1165 */ { MAD_F(0x05fc4d81) /* 0.374097350 */, 15 }, + /* 1166 */ { MAD_F(0x05fe0e84) /* 0.374525563 */, 15 }, + /* 1167 */ { MAD_F(0x05ffcfa8) /* 0.374953898 */, 15 }, + + /* 1168 */ { MAD_F(0x060190ee) /* 0.375382356 */, 15 }, + /* 1169 */ { MAD_F(0x06035254) /* 0.375810936 */, 15 }, + /* 1170 */ { MAD_F(0x060513da) /* 0.376239638 */, 15 }, + /* 1171 */ { MAD_F(0x0606d582) /* 0.376668462 */, 15 }, + /* 1172 */ { MAD_F(0x0608974a) /* 0.377097408 */, 15 }, + /* 1173 */ { MAD_F(0x060a5934) /* 0.377526476 */, 15 }, + /* 1174 */ { MAD_F(0x060c1b3d) /* 0.377955667 */, 15 }, + /* 1175 */ { MAD_F(0x060ddd68) /* 0.378384979 */, 15 }, + /* 1176 */ { MAD_F(0x060f9fb3) /* 0.378814413 */, 15 }, + /* 1177 */ { MAD_F(0x0611621f) /* 0.379243968 */, 15 }, + /* 1178 */ { MAD_F(0x061324ac) /* 0.379673646 */, 15 }, + /* 1179 */ { MAD_F(0x0614e759) /* 0.380103444 */, 15 }, + /* 1180 */ { MAD_F(0x0616aa27) /* 0.380533365 */, 15 }, + /* 1181 */ { MAD_F(0x06186d16) /* 0.380963407 */, 15 }, + /* 1182 */ { MAD_F(0x061a3025) /* 0.381393570 */, 15 }, + /* 1183 */ { MAD_F(0x061bf354) /* 0.381823855 */, 15 }, + + /* 1184 */ { MAD_F(0x061db6a5) /* 0.382254261 */, 15 }, + /* 1185 */ { MAD_F(0x061f7a15) /* 0.382684788 */, 15 }, + /* 1186 */ { MAD_F(0x06213da7) /* 0.383115436 */, 15 }, + /* 1187 */ { MAD_F(0x06230158) /* 0.383546205 */, 15 }, + /* 1188 */ { MAD_F(0x0624c52a) /* 0.383977096 */, 15 }, + /* 1189 */ { MAD_F(0x0626891d) /* 0.384408107 */, 15 }, + /* 1190 */ { MAD_F(0x06284d30) /* 0.384839239 */, 15 }, + /* 1191 */ { MAD_F(0x062a1164) /* 0.385270492 */, 15 }, + /* 1192 */ { MAD_F(0x062bd5b8) /* 0.385701865 */, 15 }, + /* 1193 */ { MAD_F(0x062d9a2c) /* 0.386133359 */, 15 }, + /* 1194 */ { MAD_F(0x062f5ec1) /* 0.386564974 */, 15 }, + /* 1195 */ { MAD_F(0x06312376) /* 0.386996709 */, 15 }, + /* 1196 */ { MAD_F(0x0632e84b) /* 0.387428565 */, 15 }, + /* 1197 */ { MAD_F(0x0634ad41) /* 0.387860541 */, 15 }, + /* 1198 */ { MAD_F(0x06367257) /* 0.388292637 */, 15 }, + /* 1199 */ { MAD_F(0x0638378d) /* 0.388724854 */, 15 }, + + /* 1200 */ { MAD_F(0x0639fce4) /* 0.389157191 */, 15 }, + /* 1201 */ { MAD_F(0x063bc25b) /* 0.389589648 */, 15 }, + /* 1202 */ { MAD_F(0x063d87f2) /* 0.390022225 */, 15 }, + /* 1203 */ { MAD_F(0x063f4da9) /* 0.390454922 */, 15 }, + /* 1204 */ { MAD_F(0x06411380) /* 0.390887739 */, 15 }, + /* 1205 */ { MAD_F(0x0642d978) /* 0.391320675 */, 15 }, + /* 1206 */ { MAD_F(0x06449f8f) /* 0.391753732 */, 15 }, + /* 1207 */ { MAD_F(0x064665c7) /* 0.392186908 */, 15 }, + /* 1208 */ { MAD_F(0x06482c1f) /* 0.392620204 */, 15 }, + /* 1209 */ { MAD_F(0x0649f297) /* 0.393053619 */, 15 }, + /* 1210 */ { MAD_F(0x064bb92f) /* 0.393487154 */, 15 }, + /* 1211 */ { MAD_F(0x064d7fe8) /* 0.393920808 */, 15 }, + /* 1212 */ { MAD_F(0x064f46c0) /* 0.394354582 */, 15 }, + /* 1213 */ { MAD_F(0x06510db8) /* 0.394788475 */, 15 }, + /* 1214 */ { MAD_F(0x0652d4d0) /* 0.395222488 */, 15 }, + /* 1215 */ { MAD_F(0x06549c09) /* 0.395656619 */, 15 }, + + /* 1216 */ { MAD_F(0x06566361) /* 0.396090870 */, 15 }, + /* 1217 */ { MAD_F(0x06582ad9) /* 0.396525239 */, 15 }, + /* 1218 */ { MAD_F(0x0659f271) /* 0.396959728 */, 15 }, + /* 1219 */ { MAD_F(0x065bba29) /* 0.397394336 */, 15 }, + /* 1220 */ { MAD_F(0x065d8201) /* 0.397829062 */, 15 }, + /* 1221 */ { MAD_F(0x065f49f9) /* 0.398263907 */, 15 }, + /* 1222 */ { MAD_F(0x06611211) /* 0.398698871 */, 15 }, + /* 1223 */ { MAD_F(0x0662da49) /* 0.399133954 */, 15 }, + /* 1224 */ { MAD_F(0x0664a2a0) /* 0.399569155 */, 15 }, + /* 1225 */ { MAD_F(0x06666b17) /* 0.400004475 */, 15 }, + /* 1226 */ { MAD_F(0x066833ae) /* 0.400439913 */, 15 }, + /* 1227 */ { MAD_F(0x0669fc65) /* 0.400875470 */, 15 }, + /* 1228 */ { MAD_F(0x066bc53c) /* 0.401311145 */, 15 }, + /* 1229 */ { MAD_F(0x066d8e32) /* 0.401746938 */, 15 }, + /* 1230 */ { MAD_F(0x066f5748) /* 0.402182850 */, 15 }, + /* 1231 */ { MAD_F(0x0671207e) /* 0.402618879 */, 15 }, + + /* 1232 */ { MAD_F(0x0672e9d4) /* 0.403055027 */, 15 }, + /* 1233 */ { MAD_F(0x0674b349) /* 0.403491293 */, 15 }, + /* 1234 */ { MAD_F(0x06767cde) /* 0.403927676 */, 15 }, + /* 1235 */ { MAD_F(0x06784692) /* 0.404364178 */, 15 }, + /* 1236 */ { MAD_F(0x067a1066) /* 0.404800797 */, 15 }, + /* 1237 */ { MAD_F(0x067bda5a) /* 0.405237535 */, 15 }, + /* 1238 */ { MAD_F(0x067da46d) /* 0.405674390 */, 15 }, + /* 1239 */ { MAD_F(0x067f6ea0) /* 0.406111362 */, 15 }, + /* 1240 */ { MAD_F(0x068138f3) /* 0.406548452 */, 15 }, + /* 1241 */ { MAD_F(0x06830365) /* 0.406985660 */, 15 }, + /* 1242 */ { MAD_F(0x0684cdf6) /* 0.407422985 */, 15 }, + /* 1243 */ { MAD_F(0x068698a8) /* 0.407860427 */, 15 }, + /* 1244 */ { MAD_F(0x06886378) /* 0.408297987 */, 15 }, + /* 1245 */ { MAD_F(0x068a2e68) /* 0.408735664 */, 15 }, + /* 1246 */ { MAD_F(0x068bf978) /* 0.409173458 */, 15 }, + /* 1247 */ { MAD_F(0x068dc4a7) /* 0.409611370 */, 15 }, + + /* 1248 */ { MAD_F(0x068f8ff5) /* 0.410049398 */, 15 }, + /* 1249 */ { MAD_F(0x06915b63) /* 0.410487544 */, 15 }, + /* 1250 */ { MAD_F(0x069326f0) /* 0.410925806 */, 15 }, + /* 1251 */ { MAD_F(0x0694f29c) /* 0.411364185 */, 15 }, + /* 1252 */ { MAD_F(0x0696be68) /* 0.411802681 */, 15 }, + /* 1253 */ { MAD_F(0x06988a54) /* 0.412241294 */, 15 }, + /* 1254 */ { MAD_F(0x069a565e) /* 0.412680024 */, 15 }, + /* 1255 */ { MAD_F(0x069c2288) /* 0.413118870 */, 15 }, + /* 1256 */ { MAD_F(0x069deed1) /* 0.413557833 */, 15 }, + /* 1257 */ { MAD_F(0x069fbb3a) /* 0.413996912 */, 15 }, + /* 1258 */ { MAD_F(0x06a187c1) /* 0.414436108 */, 15 }, + /* 1259 */ { MAD_F(0x06a35468) /* 0.414875420 */, 15 }, + /* 1260 */ { MAD_F(0x06a5212f) /* 0.415314849 */, 15 }, + /* 1261 */ { MAD_F(0x06a6ee14) /* 0.415754393 */, 15 }, + /* 1262 */ { MAD_F(0x06a8bb18) /* 0.416194054 */, 15 }, + /* 1263 */ { MAD_F(0x06aa883c) /* 0.416633831 */, 15 }, + + /* 1264 */ { MAD_F(0x06ac557f) /* 0.417073724 */, 15 }, + /* 1265 */ { MAD_F(0x06ae22e1) /* 0.417513734 */, 15 }, + /* 1266 */ { MAD_F(0x06aff062) /* 0.417953859 */, 15 }, + /* 1267 */ { MAD_F(0x06b1be03) /* 0.418394100 */, 15 }, + /* 1268 */ { MAD_F(0x06b38bc2) /* 0.418834457 */, 15 }, + /* 1269 */ { MAD_F(0x06b559a1) /* 0.419274929 */, 15 }, + /* 1270 */ { MAD_F(0x06b7279e) /* 0.419715518 */, 15 }, + /* 1271 */ { MAD_F(0x06b8f5bb) /* 0.420156222 */, 15 }, + /* 1272 */ { MAD_F(0x06bac3f6) /* 0.420597041 */, 15 }, + /* 1273 */ { MAD_F(0x06bc9251) /* 0.421037977 */, 15 }, + /* 1274 */ { MAD_F(0x06be60cb) /* 0.421479027 */, 15 }, + /* 1275 */ { MAD_F(0x06c02f63) /* 0.421920193 */, 15 }, + /* 1276 */ { MAD_F(0x06c1fe1b) /* 0.422361475 */, 15 }, + /* 1277 */ { MAD_F(0x06c3ccf1) /* 0.422802871 */, 15 }, + /* 1278 */ { MAD_F(0x06c59be7) /* 0.423244383 */, 15 }, + /* 1279 */ { MAD_F(0x06c76afb) /* 0.423686010 */, 15 }, + + /* 1280 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 15 }, + /* 1281 */ { MAD_F(0x06cb0981) /* 0.424569610 */, 15 }, + /* 1282 */ { MAD_F(0x06ccd8f2) /* 0.425011582 */, 15 }, + /* 1283 */ { MAD_F(0x06cea881) /* 0.425453669 */, 15 }, + /* 1284 */ { MAD_F(0x06d07830) /* 0.425895871 */, 15 }, + /* 1285 */ { MAD_F(0x06d247fe) /* 0.426338188 */, 15 }, + /* 1286 */ { MAD_F(0x06d417ea) /* 0.426780620 */, 15 }, + /* 1287 */ { MAD_F(0x06d5e7f5) /* 0.427223166 */, 15 }, + /* 1288 */ { MAD_F(0x06d7b81f) /* 0.427665827 */, 15 }, + /* 1289 */ { MAD_F(0x06d98868) /* 0.428108603 */, 15 }, + /* 1290 */ { MAD_F(0x06db58cf) /* 0.428551493 */, 15 }, + /* 1291 */ { MAD_F(0x06dd2955) /* 0.428994497 */, 15 }, + /* 1292 */ { MAD_F(0x06def9fa) /* 0.429437616 */, 15 }, + /* 1293 */ { MAD_F(0x06e0cabe) /* 0.429880849 */, 15 }, + /* 1294 */ { MAD_F(0x06e29ba0) /* 0.430324197 */, 15 }, + /* 1295 */ { MAD_F(0x06e46ca1) /* 0.430767659 */, 15 }, + + /* 1296 */ { MAD_F(0x06e63dc0) /* 0.431211234 */, 15 }, + /* 1297 */ { MAD_F(0x06e80efe) /* 0.431654924 */, 15 }, + /* 1298 */ { MAD_F(0x06e9e05b) /* 0.432098728 */, 15 }, + /* 1299 */ { MAD_F(0x06ebb1d6) /* 0.432542647 */, 15 }, + /* 1300 */ { MAD_F(0x06ed8370) /* 0.432986678 */, 15 }, + /* 1301 */ { MAD_F(0x06ef5529) /* 0.433430824 */, 15 }, + /* 1302 */ { MAD_F(0x06f12700) /* 0.433875084 */, 15 }, + /* 1303 */ { MAD_F(0x06f2f8f5) /* 0.434319457 */, 15 }, + /* 1304 */ { MAD_F(0x06f4cb09) /* 0.434763944 */, 15 }, + /* 1305 */ { MAD_F(0x06f69d3c) /* 0.435208545 */, 15 }, + /* 1306 */ { MAD_F(0x06f86f8d) /* 0.435653259 */, 15 }, + /* 1307 */ { MAD_F(0x06fa41fd) /* 0.436098087 */, 15 }, + /* 1308 */ { MAD_F(0x06fc148b) /* 0.436543029 */, 15 }, + /* 1309 */ { MAD_F(0x06fde737) /* 0.436988083 */, 15 }, + /* 1310 */ { MAD_F(0x06ffba02) /* 0.437433251 */, 15 }, + /* 1311 */ { MAD_F(0x07018ceb) /* 0.437878533 */, 15 }, + + /* 1312 */ { MAD_F(0x07035ff3) /* 0.438323927 */, 15 }, + /* 1313 */ { MAD_F(0x07053319) /* 0.438769435 */, 15 }, + /* 1314 */ { MAD_F(0x0707065d) /* 0.439215056 */, 15 }, + /* 1315 */ { MAD_F(0x0708d9c0) /* 0.439660790 */, 15 }, + /* 1316 */ { MAD_F(0x070aad41) /* 0.440106636 */, 15 }, + /* 1317 */ { MAD_F(0x070c80e1) /* 0.440552596 */, 15 }, + /* 1318 */ { MAD_F(0x070e549f) /* 0.440998669 */, 15 }, + /* 1319 */ { MAD_F(0x0710287b) /* 0.441444855 */, 15 }, + /* 1320 */ { MAD_F(0x0711fc75) /* 0.441891153 */, 15 }, + /* 1321 */ { MAD_F(0x0713d08d) /* 0.442337564 */, 15 }, + /* 1322 */ { MAD_F(0x0715a4c4) /* 0.442784088 */, 15 }, + /* 1323 */ { MAD_F(0x07177919) /* 0.443230724 */, 15 }, + /* 1324 */ { MAD_F(0x07194d8c) /* 0.443677473 */, 15 }, + /* 1325 */ { MAD_F(0x071b221e) /* 0.444124334 */, 15 }, + /* 1326 */ { MAD_F(0x071cf6ce) /* 0.444571308 */, 15 }, + /* 1327 */ { MAD_F(0x071ecb9b) /* 0.445018394 */, 15 }, + + /* 1328 */ { MAD_F(0x0720a087) /* 0.445465593 */, 15 }, + /* 1329 */ { MAD_F(0x07227591) /* 0.445912903 */, 15 }, + /* 1330 */ { MAD_F(0x07244ab9) /* 0.446360326 */, 15 }, + /* 1331 */ { MAD_F(0x07262000) /* 0.446807861 */, 15 }, + /* 1332 */ { MAD_F(0x0727f564) /* 0.447255509 */, 15 }, + /* 1333 */ { MAD_F(0x0729cae7) /* 0.447703268 */, 15 }, + /* 1334 */ { MAD_F(0x072ba087) /* 0.448151139 */, 15 }, + /* 1335 */ { MAD_F(0x072d7646) /* 0.448599122 */, 15 }, + /* 1336 */ { MAD_F(0x072f4c22) /* 0.449047217 */, 15 }, + /* 1337 */ { MAD_F(0x0731221d) /* 0.449495424 */, 15 }, + /* 1338 */ { MAD_F(0x0732f835) /* 0.449943742 */, 15 }, + /* 1339 */ { MAD_F(0x0734ce6c) /* 0.450392173 */, 15 }, + /* 1340 */ { MAD_F(0x0736a4c1) /* 0.450840715 */, 15 }, + /* 1341 */ { MAD_F(0x07387b33) /* 0.451289368 */, 15 }, + /* 1342 */ { MAD_F(0x073a51c4) /* 0.451738133 */, 15 }, + /* 1343 */ { MAD_F(0x073c2872) /* 0.452187010 */, 15 }, + + /* 1344 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 15 }, + /* 1345 */ { MAD_F(0x073fd628) /* 0.453085097 */, 15 }, + /* 1346 */ { MAD_F(0x0741ad30) /* 0.453534308 */, 15 }, + /* 1347 */ { MAD_F(0x07438456) /* 0.453983630 */, 15 }, + /* 1348 */ { MAD_F(0x07455b9a) /* 0.454433063 */, 15 }, + /* 1349 */ { MAD_F(0x074732fc) /* 0.454882607 */, 15 }, + /* 1350 */ { MAD_F(0x07490a7b) /* 0.455332262 */, 15 }, + /* 1351 */ { MAD_F(0x074ae218) /* 0.455782029 */, 15 }, + /* 1352 */ { MAD_F(0x074cb9d3) /* 0.456231906 */, 15 }, + /* 1353 */ { MAD_F(0x074e91ac) /* 0.456681894 */, 15 }, + /* 1354 */ { MAD_F(0x075069a3) /* 0.457131993 */, 15 }, + /* 1355 */ { MAD_F(0x075241b7) /* 0.457582203 */, 15 }, + /* 1356 */ { MAD_F(0x075419e9) /* 0.458032524 */, 15 }, + /* 1357 */ { MAD_F(0x0755f239) /* 0.458482956 */, 15 }, + /* 1358 */ { MAD_F(0x0757caa7) /* 0.458933498 */, 15 }, + /* 1359 */ { MAD_F(0x0759a332) /* 0.459384151 */, 15 }, + + /* 1360 */ { MAD_F(0x075b7bdb) /* 0.459834914 */, 15 }, + /* 1361 */ { MAD_F(0x075d54a1) /* 0.460285788 */, 15 }, + /* 1362 */ { MAD_F(0x075f2d85) /* 0.460736772 */, 15 }, + /* 1363 */ { MAD_F(0x07610687) /* 0.461187867 */, 15 }, + /* 1364 */ { MAD_F(0x0762dfa6) /* 0.461639071 */, 15 }, + /* 1365 */ { MAD_F(0x0764b8e3) /* 0.462090387 */, 15 }, + /* 1366 */ { MAD_F(0x0766923e) /* 0.462541812 */, 15 }, + /* 1367 */ { MAD_F(0x07686bb6) /* 0.462993348 */, 15 }, + /* 1368 */ { MAD_F(0x076a454c) /* 0.463444993 */, 15 }, + /* 1369 */ { MAD_F(0x076c1eff) /* 0.463896749 */, 15 }, + /* 1370 */ { MAD_F(0x076df8d0) /* 0.464348615 */, 15 }, + /* 1371 */ { MAD_F(0x076fd2be) /* 0.464800591 */, 15 }, + /* 1372 */ { MAD_F(0x0771acca) /* 0.465252676 */, 15 }, + /* 1373 */ { MAD_F(0x077386f3) /* 0.465704872 */, 15 }, + /* 1374 */ { MAD_F(0x0775613a) /* 0.466157177 */, 15 }, + /* 1375 */ { MAD_F(0x07773b9e) /* 0.466609592 */, 15 }, + + /* 1376 */ { MAD_F(0x07791620) /* 0.467062117 */, 15 }, + /* 1377 */ { MAD_F(0x077af0bf) /* 0.467514751 */, 15 }, + /* 1378 */ { MAD_F(0x077ccb7c) /* 0.467967495 */, 15 }, + /* 1379 */ { MAD_F(0x077ea656) /* 0.468420349 */, 15 }, + /* 1380 */ { MAD_F(0x0780814d) /* 0.468873312 */, 15 }, + /* 1381 */ { MAD_F(0x07825c62) /* 0.469326384 */, 15 }, + /* 1382 */ { MAD_F(0x07843794) /* 0.469779566 */, 15 }, + /* 1383 */ { MAD_F(0x078612e3) /* 0.470232857 */, 15 }, + /* 1384 */ { MAD_F(0x0787ee50) /* 0.470686258 */, 15 }, + /* 1385 */ { MAD_F(0x0789c9da) /* 0.471139767 */, 15 }, + /* 1386 */ { MAD_F(0x078ba581) /* 0.471593386 */, 15 }, + /* 1387 */ { MAD_F(0x078d8146) /* 0.472047114 */, 15 }, + /* 1388 */ { MAD_F(0x078f5d28) /* 0.472500951 */, 15 }, + /* 1389 */ { MAD_F(0x07913927) /* 0.472954896 */, 15 }, + /* 1390 */ { MAD_F(0x07931543) /* 0.473408951 */, 15 }, + /* 1391 */ { MAD_F(0x0794f17d) /* 0.473863115 */, 15 }, + + /* 1392 */ { MAD_F(0x0796cdd4) /* 0.474317388 */, 15 }, + /* 1393 */ { MAD_F(0x0798aa48) /* 0.474771769 */, 15 }, + /* 1394 */ { MAD_F(0x079a86d9) /* 0.475226259 */, 15 }, + /* 1395 */ { MAD_F(0x079c6388) /* 0.475680858 */, 15 }, + /* 1396 */ { MAD_F(0x079e4053) /* 0.476135565 */, 15 }, + /* 1397 */ { MAD_F(0x07a01d3c) /* 0.476590381 */, 15 }, + /* 1398 */ { MAD_F(0x07a1fa42) /* 0.477045306 */, 15 }, + /* 1399 */ { MAD_F(0x07a3d765) /* 0.477500339 */, 15 }, + /* 1400 */ { MAD_F(0x07a5b4a5) /* 0.477955481 */, 15 }, + /* 1401 */ { MAD_F(0x07a79202) /* 0.478410731 */, 15 }, + /* 1402 */ { MAD_F(0x07a96f7d) /* 0.478866089 */, 15 }, + /* 1403 */ { MAD_F(0x07ab4d14) /* 0.479321555 */, 15 }, + /* 1404 */ { MAD_F(0x07ad2ac8) /* 0.479777130 */, 15 }, + /* 1405 */ { MAD_F(0x07af089a) /* 0.480232813 */, 15 }, + /* 1406 */ { MAD_F(0x07b0e688) /* 0.480688604 */, 15 }, + /* 1407 */ { MAD_F(0x07b2c494) /* 0.481144503 */, 15 }, + + /* 1408 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 15 }, + /* 1409 */ { MAD_F(0x07b68102) /* 0.482056625 */, 15 }, + /* 1410 */ { MAD_F(0x07b85f64) /* 0.482512848 */, 15 }, + /* 1411 */ { MAD_F(0x07ba3de4) /* 0.482969179 */, 15 }, + /* 1412 */ { MAD_F(0x07bc1c80) /* 0.483425618 */, 15 }, + /* 1413 */ { MAD_F(0x07bdfb39) /* 0.483882164 */, 15 }, + /* 1414 */ { MAD_F(0x07bfda0f) /* 0.484338818 */, 15 }, + /* 1415 */ { MAD_F(0x07c1b902) /* 0.484795580 */, 15 }, + /* 1416 */ { MAD_F(0x07c39812) /* 0.485252449 */, 15 }, + /* 1417 */ { MAD_F(0x07c5773f) /* 0.485709426 */, 15 }, + /* 1418 */ { MAD_F(0x07c75689) /* 0.486166511 */, 15 }, + /* 1419 */ { MAD_F(0x07c935ef) /* 0.486623703 */, 15 }, + /* 1420 */ { MAD_F(0x07cb1573) /* 0.487081002 */, 15 }, + /* 1421 */ { MAD_F(0x07ccf513) /* 0.487538409 */, 15 }, + /* 1422 */ { MAD_F(0x07ced4d0) /* 0.487995923 */, 15 }, + /* 1423 */ { MAD_F(0x07d0b4aa) /* 0.488453544 */, 15 }, + + /* 1424 */ { MAD_F(0x07d294a0) /* 0.488911273 */, 15 }, + /* 1425 */ { MAD_F(0x07d474b3) /* 0.489369108 */, 15 }, + /* 1426 */ { MAD_F(0x07d654e4) /* 0.489827051 */, 15 }, + /* 1427 */ { MAD_F(0x07d83530) /* 0.490285101 */, 15 }, + /* 1428 */ { MAD_F(0x07da159a) /* 0.490743258 */, 15 }, + /* 1429 */ { MAD_F(0x07dbf620) /* 0.491201522 */, 15 }, + /* 1430 */ { MAD_F(0x07ddd6c3) /* 0.491659892 */, 15 }, + /* 1431 */ { MAD_F(0x07dfb783) /* 0.492118370 */, 15 }, + /* 1432 */ { MAD_F(0x07e1985f) /* 0.492576954 */, 15 }, + /* 1433 */ { MAD_F(0x07e37958) /* 0.493035645 */, 15 }, + /* 1434 */ { MAD_F(0x07e55a6e) /* 0.493494443 */, 15 }, + /* 1435 */ { MAD_F(0x07e73ba0) /* 0.493953348 */, 15 }, + /* 1436 */ { MAD_F(0x07e91cef) /* 0.494412359 */, 15 }, + /* 1437 */ { MAD_F(0x07eafe5a) /* 0.494871476 */, 15 }, + /* 1438 */ { MAD_F(0x07ecdfe2) /* 0.495330701 */, 15 }, + /* 1439 */ { MAD_F(0x07eec187) /* 0.495790031 */, 15 }, + + /* 1440 */ { MAD_F(0x07f0a348) /* 0.496249468 */, 15 }, + /* 1441 */ { MAD_F(0x07f28526) /* 0.496709012 */, 15 }, + /* 1442 */ { MAD_F(0x07f46720) /* 0.497168662 */, 15 }, + /* 1443 */ { MAD_F(0x07f64937) /* 0.497628418 */, 15 }, + /* 1444 */ { MAD_F(0x07f82b6a) /* 0.498088280 */, 15 }, + /* 1445 */ { MAD_F(0x07fa0dba) /* 0.498548248 */, 15 }, + /* 1446 */ { MAD_F(0x07fbf026) /* 0.499008323 */, 15 }, + /* 1447 */ { MAD_F(0x07fdd2af) /* 0.499468503 */, 15 }, + /* 1448 */ { MAD_F(0x07ffb554) /* 0.499928790 */, 15 }, + /* 1449 */ { MAD_F(0x0400cc0b) /* 0.250194591 */, 16 }, + /* 1450 */ { MAD_F(0x0401bd7a) /* 0.250424840 */, 16 }, + /* 1451 */ { MAD_F(0x0402aef7) /* 0.250655143 */, 16 }, + /* 1452 */ { MAD_F(0x0403a083) /* 0.250885498 */, 16 }, + /* 1453 */ { MAD_F(0x0404921c) /* 0.251115906 */, 16 }, + /* 1454 */ { MAD_F(0x040583c4) /* 0.251346367 */, 16 }, + /* 1455 */ { MAD_F(0x0406757a) /* 0.251576880 */, 16 }, + + /* 1456 */ { MAD_F(0x0407673f) /* 0.251807447 */, 16 }, + /* 1457 */ { MAD_F(0x04085911) /* 0.252038066 */, 16 }, + /* 1458 */ { MAD_F(0x04094af1) /* 0.252268738 */, 16 }, + /* 1459 */ { MAD_F(0x040a3ce0) /* 0.252499463 */, 16 }, + /* 1460 */ { MAD_F(0x040b2edd) /* 0.252730240 */, 16 }, + /* 1461 */ { MAD_F(0x040c20e8) /* 0.252961071 */, 16 }, + /* 1462 */ { MAD_F(0x040d1301) /* 0.253191953 */, 16 }, + /* 1463 */ { MAD_F(0x040e0529) /* 0.253422889 */, 16 }, + /* 1464 */ { MAD_F(0x040ef75e) /* 0.253653877 */, 16 }, + /* 1465 */ { MAD_F(0x040fe9a1) /* 0.253884918 */, 16 }, + /* 1466 */ { MAD_F(0x0410dbf3) /* 0.254116011 */, 16 }, + /* 1467 */ { MAD_F(0x0411ce53) /* 0.254347157 */, 16 }, + /* 1468 */ { MAD_F(0x0412c0c1) /* 0.254578356 */, 16 }, + /* 1469 */ { MAD_F(0x0413b33d) /* 0.254809606 */, 16 }, + /* 1470 */ { MAD_F(0x0414a5c7) /* 0.255040910 */, 16 }, + /* 1471 */ { MAD_F(0x0415985f) /* 0.255272266 */, 16 }, + + /* 1472 */ { MAD_F(0x04168b05) /* 0.255503674 */, 16 }, + /* 1473 */ { MAD_F(0x04177db9) /* 0.255735135 */, 16 }, + /* 1474 */ { MAD_F(0x0418707c) /* 0.255966648 */, 16 }, + /* 1475 */ { MAD_F(0x0419634c) /* 0.256198213 */, 16 }, + /* 1476 */ { MAD_F(0x041a562a) /* 0.256429831 */, 16 }, + /* 1477 */ { MAD_F(0x041b4917) /* 0.256661501 */, 16 }, + /* 1478 */ { MAD_F(0x041c3c11) /* 0.256893223 */, 16 }, + /* 1479 */ { MAD_F(0x041d2f1a) /* 0.257124998 */, 16 }, + /* 1480 */ { MAD_F(0x041e2230) /* 0.257356825 */, 16 }, + /* 1481 */ { MAD_F(0x041f1555) /* 0.257588704 */, 16 }, + /* 1482 */ { MAD_F(0x04200888) /* 0.257820635 */, 16 }, + /* 1483 */ { MAD_F(0x0420fbc8) /* 0.258052619 */, 16 }, + /* 1484 */ { MAD_F(0x0421ef17) /* 0.258284654 */, 16 }, + /* 1485 */ { MAD_F(0x0422e273) /* 0.258516742 */, 16 }, + /* 1486 */ { MAD_F(0x0423d5de) /* 0.258748882 */, 16 }, + /* 1487 */ { MAD_F(0x0424c956) /* 0.258981074 */, 16 }, + + /* 1488 */ { MAD_F(0x0425bcdd) /* 0.259213318 */, 16 }, + /* 1489 */ { MAD_F(0x0426b071) /* 0.259445614 */, 16 }, + /* 1490 */ { MAD_F(0x0427a414) /* 0.259677962 */, 16 }, + /* 1491 */ { MAD_F(0x042897c4) /* 0.259910362 */, 16 }, + /* 1492 */ { MAD_F(0x04298b83) /* 0.260142814 */, 16 }, + /* 1493 */ { MAD_F(0x042a7f4f) /* 0.260375318 */, 16 }, + /* 1494 */ { MAD_F(0x042b7329) /* 0.260607874 */, 16 }, + /* 1495 */ { MAD_F(0x042c6711) /* 0.260840481 */, 16 }, + /* 1496 */ { MAD_F(0x042d5b07) /* 0.261073141 */, 16 }, + /* 1497 */ { MAD_F(0x042e4f0b) /* 0.261305852 */, 16 }, + /* 1498 */ { MAD_F(0x042f431d) /* 0.261538616 */, 16 }, + /* 1499 */ { MAD_F(0x0430373d) /* 0.261771431 */, 16 }, + /* 1500 */ { MAD_F(0x04312b6b) /* 0.262004297 */, 16 }, + /* 1501 */ { MAD_F(0x04321fa6) /* 0.262237216 */, 16 }, + /* 1502 */ { MAD_F(0x043313f0) /* 0.262470186 */, 16 }, + /* 1503 */ { MAD_F(0x04340847) /* 0.262703208 */, 16 }, + + /* 1504 */ { MAD_F(0x0434fcad) /* 0.262936282 */, 16 }, + /* 1505 */ { MAD_F(0x0435f120) /* 0.263169407 */, 16 }, + /* 1506 */ { MAD_F(0x0436e5a1) /* 0.263402584 */, 16 }, + /* 1507 */ { MAD_F(0x0437da2f) /* 0.263635813 */, 16 }, + /* 1508 */ { MAD_F(0x0438cecc) /* 0.263869093 */, 16 }, + /* 1509 */ { MAD_F(0x0439c377) /* 0.264102425 */, 16 }, + /* 1510 */ { MAD_F(0x043ab82f) /* 0.264335808 */, 16 }, + /* 1511 */ { MAD_F(0x043bacf5) /* 0.264569243 */, 16 }, + /* 1512 */ { MAD_F(0x043ca1c9) /* 0.264802730 */, 16 }, + /* 1513 */ { MAD_F(0x043d96ab) /* 0.265036267 */, 16 }, + /* 1514 */ { MAD_F(0x043e8b9b) /* 0.265269857 */, 16 }, + /* 1515 */ { MAD_F(0x043f8098) /* 0.265503498 */, 16 }, + /* 1516 */ { MAD_F(0x044075a3) /* 0.265737190 */, 16 }, + /* 1517 */ { MAD_F(0x04416abc) /* 0.265970933 */, 16 }, + /* 1518 */ { MAD_F(0x04425fe3) /* 0.266204728 */, 16 }, + /* 1519 */ { MAD_F(0x04435518) /* 0.266438574 */, 16 }, + + /* 1520 */ { MAD_F(0x04444a5a) /* 0.266672472 */, 16 }, + /* 1521 */ { MAD_F(0x04453fab) /* 0.266906421 */, 16 }, + /* 1522 */ { MAD_F(0x04463508) /* 0.267140421 */, 16 }, + /* 1523 */ { MAD_F(0x04472a74) /* 0.267374472 */, 16 }, + /* 1524 */ { MAD_F(0x04481fee) /* 0.267608575 */, 16 }, + /* 1525 */ { MAD_F(0x04491575) /* 0.267842729 */, 16 }, + /* 1526 */ { MAD_F(0x044a0b0a) /* 0.268076934 */, 16 }, + /* 1527 */ { MAD_F(0x044b00ac) /* 0.268311190 */, 16 }, + /* 1528 */ { MAD_F(0x044bf65d) /* 0.268545497 */, 16 }, + /* 1529 */ { MAD_F(0x044cec1b) /* 0.268779856 */, 16 }, + /* 1530 */ { MAD_F(0x044de1e7) /* 0.269014265 */, 16 }, + /* 1531 */ { MAD_F(0x044ed7c0) /* 0.269248726 */, 16 }, + /* 1532 */ { MAD_F(0x044fcda8) /* 0.269483238 */, 16 }, + /* 1533 */ { MAD_F(0x0450c39c) /* 0.269717800 */, 16 }, + /* 1534 */ { MAD_F(0x0451b99f) /* 0.269952414 */, 16 }, + /* 1535 */ { MAD_F(0x0452afaf) /* 0.270187079 */, 16 }, + + /* 1536 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 16 }, + /* 1537 */ { MAD_F(0x04549bf9) /* 0.270656561 */, 16 }, + /* 1538 */ { MAD_F(0x04559232) /* 0.270891379 */, 16 }, + /* 1539 */ { MAD_F(0x04568879) /* 0.271126247 */, 16 }, + /* 1540 */ { MAD_F(0x04577ece) /* 0.271361166 */, 16 }, + /* 1541 */ { MAD_F(0x04587530) /* 0.271596136 */, 16 }, + /* 1542 */ { MAD_F(0x04596ba0) /* 0.271831157 */, 16 }, + /* 1543 */ { MAD_F(0x045a621e) /* 0.272066229 */, 16 }, + /* 1544 */ { MAD_F(0x045b58a9) /* 0.272301352 */, 16 }, + /* 1545 */ { MAD_F(0x045c4f42) /* 0.272536525 */, 16 }, + /* 1546 */ { MAD_F(0x045d45e9) /* 0.272771749 */, 16 }, + /* 1547 */ { MAD_F(0x045e3c9d) /* 0.273007024 */, 16 }, + /* 1548 */ { MAD_F(0x045f335e) /* 0.273242350 */, 16 }, + /* 1549 */ { MAD_F(0x04602a2e) /* 0.273477726 */, 16 }, + /* 1550 */ { MAD_F(0x0461210b) /* 0.273713153 */, 16 }, + /* 1551 */ { MAD_F(0x046217f5) /* 0.273948630 */, 16 }, + + /* 1552 */ { MAD_F(0x04630eed) /* 0.274184158 */, 16 }, + /* 1553 */ { MAD_F(0x046405f3) /* 0.274419737 */, 16 }, + /* 1554 */ { MAD_F(0x0464fd06) /* 0.274655366 */, 16 }, + /* 1555 */ { MAD_F(0x0465f427) /* 0.274891046 */, 16 }, + /* 1556 */ { MAD_F(0x0466eb55) /* 0.275126776 */, 16 }, + /* 1557 */ { MAD_F(0x0467e291) /* 0.275362557 */, 16 }, + /* 1558 */ { MAD_F(0x0468d9db) /* 0.275598389 */, 16 }, + /* 1559 */ { MAD_F(0x0469d132) /* 0.275834270 */, 16 }, + /* 1560 */ { MAD_F(0x046ac896) /* 0.276070203 */, 16 }, + /* 1561 */ { MAD_F(0x046bc009) /* 0.276306185 */, 16 }, + /* 1562 */ { MAD_F(0x046cb788) /* 0.276542218 */, 16 }, + /* 1563 */ { MAD_F(0x046daf15) /* 0.276778302 */, 16 }, + /* 1564 */ { MAD_F(0x046ea6b0) /* 0.277014435 */, 16 }, + /* 1565 */ { MAD_F(0x046f9e58) /* 0.277250619 */, 16 }, + /* 1566 */ { MAD_F(0x0470960e) /* 0.277486854 */, 16 }, + /* 1567 */ { MAD_F(0x04718dd1) /* 0.277723139 */, 16 }, + + /* 1568 */ { MAD_F(0x047285a2) /* 0.277959474 */, 16 }, + /* 1569 */ { MAD_F(0x04737d80) /* 0.278195859 */, 16 }, + /* 1570 */ { MAD_F(0x0474756c) /* 0.278432294 */, 16 }, + /* 1571 */ { MAD_F(0x04756d65) /* 0.278668780 */, 16 }, + /* 1572 */ { MAD_F(0x0476656b) /* 0.278905316 */, 16 }, + /* 1573 */ { MAD_F(0x04775d7f) /* 0.279141902 */, 16 }, + /* 1574 */ { MAD_F(0x047855a1) /* 0.279378538 */, 16 }, + /* 1575 */ { MAD_F(0x04794dd0) /* 0.279615224 */, 16 }, + /* 1576 */ { MAD_F(0x047a460c) /* 0.279851960 */, 16 }, + /* 1577 */ { MAD_F(0x047b3e56) /* 0.280088747 */, 16 }, + /* 1578 */ { MAD_F(0x047c36ae) /* 0.280325583 */, 16 }, + /* 1579 */ { MAD_F(0x047d2f12) /* 0.280562470 */, 16 }, + /* 1580 */ { MAD_F(0x047e2784) /* 0.280799406 */, 16 }, + /* 1581 */ { MAD_F(0x047f2004) /* 0.281036393 */, 16 }, + /* 1582 */ { MAD_F(0x04801891) /* 0.281273429 */, 16 }, + /* 1583 */ { MAD_F(0x0481112b) /* 0.281510516 */, 16 }, + + /* 1584 */ { MAD_F(0x048209d3) /* 0.281747652 */, 16 }, + /* 1585 */ { MAD_F(0x04830288) /* 0.281984838 */, 16 }, + /* 1586 */ { MAD_F(0x0483fb4b) /* 0.282222075 */, 16 }, + /* 1587 */ { MAD_F(0x0484f41b) /* 0.282459361 */, 16 }, + /* 1588 */ { MAD_F(0x0485ecf8) /* 0.282696697 */, 16 }, + /* 1589 */ { MAD_F(0x0486e5e3) /* 0.282934082 */, 16 }, + /* 1590 */ { MAD_F(0x0487dedb) /* 0.283171518 */, 16 }, + /* 1591 */ { MAD_F(0x0488d7e1) /* 0.283409003 */, 16 }, + /* 1592 */ { MAD_F(0x0489d0f4) /* 0.283646538 */, 16 }, + /* 1593 */ { MAD_F(0x048aca14) /* 0.283884123 */, 16 }, + /* 1594 */ { MAD_F(0x048bc341) /* 0.284121757 */, 16 }, + /* 1595 */ { MAD_F(0x048cbc7c) /* 0.284359441 */, 16 }, + /* 1596 */ { MAD_F(0x048db5c4) /* 0.284597175 */, 16 }, + /* 1597 */ { MAD_F(0x048eaf1a) /* 0.284834959 */, 16 }, + /* 1598 */ { MAD_F(0x048fa87d) /* 0.285072792 */, 16 }, + /* 1599 */ { MAD_F(0x0490a1ed) /* 0.285310675 */, 16 }, + + /* 1600 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 16 }, + /* 1601 */ { MAD_F(0x049294f5) /* 0.285786589 */, 16 }, + /* 1602 */ { MAD_F(0x04938e8d) /* 0.286024621 */, 16 }, + /* 1603 */ { MAD_F(0x04948833) /* 0.286262702 */, 16 }, + /* 1604 */ { MAD_F(0x049581e5) /* 0.286500832 */, 16 }, + /* 1605 */ { MAD_F(0x04967ba5) /* 0.286739012 */, 16 }, + /* 1606 */ { MAD_F(0x04977573) /* 0.286977242 */, 16 }, + /* 1607 */ { MAD_F(0x04986f4d) /* 0.287215521 */, 16 }, + /* 1608 */ { MAD_F(0x04996935) /* 0.287453849 */, 16 }, + /* 1609 */ { MAD_F(0x049a632a) /* 0.287692227 */, 16 }, + /* 1610 */ { MAD_F(0x049b5d2c) /* 0.287930654 */, 16 }, + /* 1611 */ { MAD_F(0x049c573c) /* 0.288169131 */, 16 }, + /* 1612 */ { MAD_F(0x049d5159) /* 0.288407657 */, 16 }, + /* 1613 */ { MAD_F(0x049e4b83) /* 0.288646232 */, 16 }, + /* 1614 */ { MAD_F(0x049f45ba) /* 0.288884857 */, 16 }, + /* 1615 */ { MAD_F(0x04a03ffe) /* 0.289123530 */, 16 }, + + /* 1616 */ { MAD_F(0x04a13a50) /* 0.289362253 */, 16 }, + /* 1617 */ { MAD_F(0x04a234af) /* 0.289601026 */, 16 }, + /* 1618 */ { MAD_F(0x04a32f1b) /* 0.289839847 */, 16 }, + /* 1619 */ { MAD_F(0x04a42995) /* 0.290078718 */, 16 }, + /* 1620 */ { MAD_F(0x04a5241b) /* 0.290317638 */, 16 }, + /* 1621 */ { MAD_F(0x04a61eaf) /* 0.290556607 */, 16 }, + /* 1622 */ { MAD_F(0x04a71950) /* 0.290795626 */, 16 }, + /* 1623 */ { MAD_F(0x04a813fe) /* 0.291034693 */, 16 }, + /* 1624 */ { MAD_F(0x04a90eba) /* 0.291273810 */, 16 }, + /* 1625 */ { MAD_F(0x04aa0982) /* 0.291512975 */, 16 }, + /* 1626 */ { MAD_F(0x04ab0458) /* 0.291752190 */, 16 }, + /* 1627 */ { MAD_F(0x04abff3b) /* 0.291991453 */, 16 }, + /* 1628 */ { MAD_F(0x04acfa2b) /* 0.292230766 */, 16 }, + /* 1629 */ { MAD_F(0x04adf528) /* 0.292470128 */, 16 }, + /* 1630 */ { MAD_F(0x04aef032) /* 0.292709539 */, 16 }, + /* 1631 */ { MAD_F(0x04afeb4a) /* 0.292948998 */, 16 }, + + /* 1632 */ { MAD_F(0x04b0e66e) /* 0.293188507 */, 16 }, + /* 1633 */ { MAD_F(0x04b1e1a0) /* 0.293428065 */, 16 }, + /* 1634 */ { MAD_F(0x04b2dcdf) /* 0.293667671 */, 16 }, + /* 1635 */ { MAD_F(0x04b3d82b) /* 0.293907326 */, 16 }, + /* 1636 */ { MAD_F(0x04b4d384) /* 0.294147031 */, 16 }, + /* 1637 */ { MAD_F(0x04b5ceea) /* 0.294386784 */, 16 }, + /* 1638 */ { MAD_F(0x04b6ca5e) /* 0.294626585 */, 16 }, + /* 1639 */ { MAD_F(0x04b7c5de) /* 0.294866436 */, 16 }, + /* 1640 */ { MAD_F(0x04b8c16c) /* 0.295106336 */, 16 }, + /* 1641 */ { MAD_F(0x04b9bd06) /* 0.295346284 */, 16 }, + /* 1642 */ { MAD_F(0x04bab8ae) /* 0.295586281 */, 16 }, + /* 1643 */ { MAD_F(0x04bbb463) /* 0.295826327 */, 16 }, + /* 1644 */ { MAD_F(0x04bcb024) /* 0.296066421 */, 16 }, + /* 1645 */ { MAD_F(0x04bdabf3) /* 0.296306564 */, 16 }, + /* 1646 */ { MAD_F(0x04bea7cf) /* 0.296546756 */, 16 }, + /* 1647 */ { MAD_F(0x04bfa3b8) /* 0.296786996 */, 16 }, + + /* 1648 */ { MAD_F(0x04c09faf) /* 0.297027285 */, 16 }, + /* 1649 */ { MAD_F(0x04c19bb2) /* 0.297267623 */, 16 }, + /* 1650 */ { MAD_F(0x04c297c2) /* 0.297508009 */, 16 }, + /* 1651 */ { MAD_F(0x04c393df) /* 0.297748444 */, 16 }, + /* 1652 */ { MAD_F(0x04c49009) /* 0.297988927 */, 16 }, + /* 1653 */ { MAD_F(0x04c58c41) /* 0.298229459 */, 16 }, + /* 1654 */ { MAD_F(0x04c68885) /* 0.298470039 */, 16 }, + /* 1655 */ { MAD_F(0x04c784d6) /* 0.298710668 */, 16 }, + /* 1656 */ { MAD_F(0x04c88135) /* 0.298951346 */, 16 }, + /* 1657 */ { MAD_F(0x04c97da0) /* 0.299192071 */, 16 }, + /* 1658 */ { MAD_F(0x04ca7a18) /* 0.299432846 */, 16 }, + /* 1659 */ { MAD_F(0x04cb769e) /* 0.299673668 */, 16 }, + /* 1660 */ { MAD_F(0x04cc7330) /* 0.299914539 */, 16 }, + /* 1661 */ { MAD_F(0x04cd6fcf) /* 0.300155459 */, 16 }, + /* 1662 */ { MAD_F(0x04ce6c7b) /* 0.300396426 */, 16 }, + /* 1663 */ { MAD_F(0x04cf6935) /* 0.300637443 */, 16 }, + + /* 1664 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 16 }, + /* 1665 */ { MAD_F(0x04d162ce) /* 0.301119620 */, 16 }, + /* 1666 */ { MAD_F(0x04d25fae) /* 0.301360781 */, 16 }, + /* 1667 */ { MAD_F(0x04d35c9b) /* 0.301601990 */, 16 }, + /* 1668 */ { MAD_F(0x04d45995) /* 0.301843247 */, 16 }, + /* 1669 */ { MAD_F(0x04d5569c) /* 0.302084553 */, 16 }, + /* 1670 */ { MAD_F(0x04d653b0) /* 0.302325907 */, 16 }, + /* 1671 */ { MAD_F(0x04d750d1) /* 0.302567309 */, 16 }, + /* 1672 */ { MAD_F(0x04d84dff) /* 0.302808759 */, 16 }, + /* 1673 */ { MAD_F(0x04d94b3a) /* 0.303050257 */, 16 }, + /* 1674 */ { MAD_F(0x04da4881) /* 0.303291804 */, 16 }, + /* 1675 */ { MAD_F(0x04db45d6) /* 0.303533399 */, 16 }, + /* 1676 */ { MAD_F(0x04dc4337) /* 0.303775041 */, 16 }, + /* 1677 */ { MAD_F(0x04dd40a6) /* 0.304016732 */, 16 }, + /* 1678 */ { MAD_F(0x04de3e21) /* 0.304258471 */, 16 }, + /* 1679 */ { MAD_F(0x04df3ba9) /* 0.304500257 */, 16 }, + + /* 1680 */ { MAD_F(0x04e0393e) /* 0.304742092 */, 16 }, + /* 1681 */ { MAD_F(0x04e136e0) /* 0.304983975 */, 16 }, + /* 1682 */ { MAD_F(0x04e2348f) /* 0.305225906 */, 16 }, + /* 1683 */ { MAD_F(0x04e3324b) /* 0.305467885 */, 16 }, + /* 1684 */ { MAD_F(0x04e43013) /* 0.305709911 */, 16 }, + /* 1685 */ { MAD_F(0x04e52de9) /* 0.305951986 */, 16 }, + /* 1686 */ { MAD_F(0x04e62bcb) /* 0.306194108 */, 16 }, + /* 1687 */ { MAD_F(0x04e729ba) /* 0.306436279 */, 16 }, + /* 1688 */ { MAD_F(0x04e827b6) /* 0.306678497 */, 16 }, + /* 1689 */ { MAD_F(0x04e925bf) /* 0.306920763 */, 16 }, + /* 1690 */ { MAD_F(0x04ea23d4) /* 0.307163077 */, 16 }, + /* 1691 */ { MAD_F(0x04eb21f7) /* 0.307405438 */, 16 }, + /* 1692 */ { MAD_F(0x04ec2026) /* 0.307647848 */, 16 }, + /* 1693 */ { MAD_F(0x04ed1e62) /* 0.307890305 */, 16 }, + /* 1694 */ { MAD_F(0x04ee1cab) /* 0.308132810 */, 16 }, + /* 1695 */ { MAD_F(0x04ef1b01) /* 0.308375362 */, 16 }, + + /* 1696 */ { MAD_F(0x04f01963) /* 0.308617963 */, 16 }, + /* 1697 */ { MAD_F(0x04f117d3) /* 0.308860611 */, 16 }, + /* 1698 */ { MAD_F(0x04f2164f) /* 0.309103306 */, 16 }, + /* 1699 */ { MAD_F(0x04f314d8) /* 0.309346050 */, 16 }, + /* 1700 */ { MAD_F(0x04f4136d) /* 0.309588841 */, 16 }, + /* 1701 */ { MAD_F(0x04f51210) /* 0.309831679 */, 16 }, + /* 1702 */ { MAD_F(0x04f610bf) /* 0.310074565 */, 16 }, + /* 1703 */ { MAD_F(0x04f70f7b) /* 0.310317499 */, 16 }, + /* 1704 */ { MAD_F(0x04f80e44) /* 0.310560480 */, 16 }, + /* 1705 */ { MAD_F(0x04f90d19) /* 0.310803509 */, 16 }, + /* 1706 */ { MAD_F(0x04fa0bfc) /* 0.311046586 */, 16 }, + /* 1707 */ { MAD_F(0x04fb0aeb) /* 0.311289710 */, 16 }, + /* 1708 */ { MAD_F(0x04fc09e7) /* 0.311532881 */, 16 }, + /* 1709 */ { MAD_F(0x04fd08ef) /* 0.311776100 */, 16 }, + /* 1710 */ { MAD_F(0x04fe0805) /* 0.312019366 */, 16 }, + /* 1711 */ { MAD_F(0x04ff0727) /* 0.312262680 */, 16 }, + + /* 1712 */ { MAD_F(0x05000655) /* 0.312506041 */, 16 }, + /* 1713 */ { MAD_F(0x05010591) /* 0.312749449 */, 16 }, + /* 1714 */ { MAD_F(0x050204d9) /* 0.312992905 */, 16 }, + /* 1715 */ { MAD_F(0x0503042e) /* 0.313236408 */, 16 }, + /* 1716 */ { MAD_F(0x0504038f) /* 0.313479959 */, 16 }, + /* 1717 */ { MAD_F(0x050502fe) /* 0.313723556 */, 16 }, + /* 1718 */ { MAD_F(0x05060279) /* 0.313967202 */, 16 }, + /* 1719 */ { MAD_F(0x05070200) /* 0.314210894 */, 16 }, + /* 1720 */ { MAD_F(0x05080195) /* 0.314454634 */, 16 }, + /* 1721 */ { MAD_F(0x05090136) /* 0.314698420 */, 16 }, + /* 1722 */ { MAD_F(0x050a00e3) /* 0.314942255 */, 16 }, + /* 1723 */ { MAD_F(0x050b009e) /* 0.315186136 */, 16 }, + /* 1724 */ { MAD_F(0x050c0065) /* 0.315430064 */, 16 }, + /* 1725 */ { MAD_F(0x050d0039) /* 0.315674040 */, 16 }, + /* 1726 */ { MAD_F(0x050e0019) /* 0.315918063 */, 16 }, + /* 1727 */ { MAD_F(0x050f0006) /* 0.316162133 */, 16 }, + + /* 1728 */ { MAD_F(0x05100000) /* 0.316406250 */, 16 }, + /* 1729 */ { MAD_F(0x05110006) /* 0.316650414 */, 16 }, + /* 1730 */ { MAD_F(0x05120019) /* 0.316894625 */, 16 }, + /* 1731 */ { MAD_F(0x05130039) /* 0.317138884 */, 16 }, + /* 1732 */ { MAD_F(0x05140065) /* 0.317383189 */, 16 }, + /* 1733 */ { MAD_F(0x0515009e) /* 0.317627541 */, 16 }, + /* 1734 */ { MAD_F(0x051600e3) /* 0.317871941 */, 16 }, + /* 1735 */ { MAD_F(0x05170135) /* 0.318116387 */, 16 }, + /* 1736 */ { MAD_F(0x05180194) /* 0.318360880 */, 16 }, + /* 1737 */ { MAD_F(0x051901ff) /* 0.318605421 */, 16 }, + /* 1738 */ { MAD_F(0x051a0277) /* 0.318850008 */, 16 }, + /* 1739 */ { MAD_F(0x051b02fc) /* 0.319094642 */, 16 }, + /* 1740 */ { MAD_F(0x051c038d) /* 0.319339323 */, 16 }, + /* 1741 */ { MAD_F(0x051d042a) /* 0.319584051 */, 16 }, + /* 1742 */ { MAD_F(0x051e04d4) /* 0.319828826 */, 16 }, + /* 1743 */ { MAD_F(0x051f058b) /* 0.320073647 */, 16 }, + + /* 1744 */ { MAD_F(0x0520064f) /* 0.320318516 */, 16 }, + /* 1745 */ { MAD_F(0x0521071f) /* 0.320563431 */, 16 }, + /* 1746 */ { MAD_F(0x052207fb) /* 0.320808393 */, 16 }, + /* 1747 */ { MAD_F(0x052308e4) /* 0.321053402 */, 16 }, + /* 1748 */ { MAD_F(0x052409da) /* 0.321298457 */, 16 }, + /* 1749 */ { MAD_F(0x05250adc) /* 0.321543560 */, 16 }, + /* 1750 */ { MAD_F(0x05260bea) /* 0.321788709 */, 16 }, + /* 1751 */ { MAD_F(0x05270d06) /* 0.322033904 */, 16 }, + /* 1752 */ { MAD_F(0x05280e2d) /* 0.322279147 */, 16 }, + /* 1753 */ { MAD_F(0x05290f62) /* 0.322524436 */, 16 }, + /* 1754 */ { MAD_F(0x052a10a3) /* 0.322769771 */, 16 }, + /* 1755 */ { MAD_F(0x052b11f0) /* 0.323015154 */, 16 }, + /* 1756 */ { MAD_F(0x052c134a) /* 0.323260583 */, 16 }, + /* 1757 */ { MAD_F(0x052d14b0) /* 0.323506058 */, 16 }, + /* 1758 */ { MAD_F(0x052e1623) /* 0.323751580 */, 16 }, + /* 1759 */ { MAD_F(0x052f17a2) /* 0.323997149 */, 16 }, + + /* 1760 */ { MAD_F(0x0530192e) /* 0.324242764 */, 16 }, + /* 1761 */ { MAD_F(0x05311ac6) /* 0.324488426 */, 16 }, + /* 1762 */ { MAD_F(0x05321c6b) /* 0.324734134 */, 16 }, + /* 1763 */ { MAD_F(0x05331e1c) /* 0.324979889 */, 16 }, + /* 1764 */ { MAD_F(0x05341fda) /* 0.325225690 */, 16 }, + /* 1765 */ { MAD_F(0x053521a4) /* 0.325471538 */, 16 }, + /* 1766 */ { MAD_F(0x0536237b) /* 0.325717432 */, 16 }, + /* 1767 */ { MAD_F(0x0537255e) /* 0.325963372 */, 16 }, + /* 1768 */ { MAD_F(0x0538274e) /* 0.326209359 */, 16 }, + /* 1769 */ { MAD_F(0x0539294a) /* 0.326455392 */, 16 }, + /* 1770 */ { MAD_F(0x053a2b52) /* 0.326701472 */, 16 }, + /* 1771 */ { MAD_F(0x053b2d67) /* 0.326947598 */, 16 }, + /* 1772 */ { MAD_F(0x053c2f89) /* 0.327193770 */, 16 }, + /* 1773 */ { MAD_F(0x053d31b6) /* 0.327439989 */, 16 }, + /* 1774 */ { MAD_F(0x053e33f1) /* 0.327686254 */, 16 }, + /* 1775 */ { MAD_F(0x053f3637) /* 0.327932565 */, 16 }, + + /* 1776 */ { MAD_F(0x0540388a) /* 0.328178922 */, 16 }, + /* 1777 */ { MAD_F(0x05413aea) /* 0.328425326 */, 16 }, + /* 1778 */ { MAD_F(0x05423d56) /* 0.328671776 */, 16 }, + /* 1779 */ { MAD_F(0x05433fce) /* 0.328918272 */, 16 }, + /* 1780 */ { MAD_F(0x05444253) /* 0.329164814 */, 16 }, + /* 1781 */ { MAD_F(0x054544e4) /* 0.329411403 */, 16 }, + /* 1782 */ { MAD_F(0x05464781) /* 0.329658038 */, 16 }, + /* 1783 */ { MAD_F(0x05474a2b) /* 0.329904718 */, 16 }, + /* 1784 */ { MAD_F(0x05484ce2) /* 0.330151445 */, 16 }, + /* 1785 */ { MAD_F(0x05494fa4) /* 0.330398218 */, 16 }, + /* 1786 */ { MAD_F(0x054a5273) /* 0.330645037 */, 16 }, + /* 1787 */ { MAD_F(0x054b554e) /* 0.330891903 */, 16 }, + /* 1788 */ { MAD_F(0x054c5836) /* 0.331138814 */, 16 }, + /* 1789 */ { MAD_F(0x054d5b2a) /* 0.331385771 */, 16 }, + /* 1790 */ { MAD_F(0x054e5e2b) /* 0.331632774 */, 16 }, + /* 1791 */ { MAD_F(0x054f6138) /* 0.331879824 */, 16 }, + + /* 1792 */ { MAD_F(0x05506451) /* 0.332126919 */, 16 }, + /* 1793 */ { MAD_F(0x05516776) /* 0.332374060 */, 16 }, + /* 1794 */ { MAD_F(0x05526aa8) /* 0.332621247 */, 16 }, + /* 1795 */ { MAD_F(0x05536de6) /* 0.332868480 */, 16 }, + /* 1796 */ { MAD_F(0x05547131) /* 0.333115759 */, 16 }, + /* 1797 */ { MAD_F(0x05557487) /* 0.333363084 */, 16 }, + /* 1798 */ { MAD_F(0x055677ea) /* 0.333610455 */, 16 }, + /* 1799 */ { MAD_F(0x05577b5a) /* 0.333857872 */, 16 }, + /* 1800 */ { MAD_F(0x05587ed5) /* 0.334105334 */, 16 }, + /* 1801 */ { MAD_F(0x0559825e) /* 0.334352843 */, 16 }, + /* 1802 */ { MAD_F(0x055a85f2) /* 0.334600397 */, 16 }, + /* 1803 */ { MAD_F(0x055b8992) /* 0.334847997 */, 16 }, + /* 1804 */ { MAD_F(0x055c8d3f) /* 0.335095642 */, 16 }, + /* 1805 */ { MAD_F(0x055d90f9) /* 0.335343334 */, 16 }, + /* 1806 */ { MAD_F(0x055e94be) /* 0.335591071 */, 16 }, + /* 1807 */ { MAD_F(0x055f9890) /* 0.335838854 */, 16 }, + + /* 1808 */ { MAD_F(0x05609c6e) /* 0.336086683 */, 16 }, + /* 1809 */ { MAD_F(0x0561a058) /* 0.336334557 */, 16 }, + /* 1810 */ { MAD_F(0x0562a44f) /* 0.336582477 */, 16 }, + /* 1811 */ { MAD_F(0x0563a851) /* 0.336830443 */, 16 }, + /* 1812 */ { MAD_F(0x0564ac60) /* 0.337078454 */, 16 }, + /* 1813 */ { MAD_F(0x0565b07c) /* 0.337326511 */, 16 }, + /* 1814 */ { MAD_F(0x0566b4a3) /* 0.337574614 */, 16 }, + /* 1815 */ { MAD_F(0x0567b8d7) /* 0.337822762 */, 16 }, + /* 1816 */ { MAD_F(0x0568bd17) /* 0.338070956 */, 16 }, + /* 1817 */ { MAD_F(0x0569c163) /* 0.338319195 */, 16 }, + /* 1818 */ { MAD_F(0x056ac5bc) /* 0.338567480 */, 16 }, + /* 1819 */ { MAD_F(0x056bca20) /* 0.338815811 */, 16 }, + /* 1820 */ { MAD_F(0x056cce91) /* 0.339064186 */, 16 }, + /* 1821 */ { MAD_F(0x056dd30e) /* 0.339312608 */, 16 }, + /* 1822 */ { MAD_F(0x056ed798) /* 0.339561075 */, 16 }, + /* 1823 */ { MAD_F(0x056fdc2d) /* 0.339809587 */, 16 }, + + /* 1824 */ { MAD_F(0x0570e0cf) /* 0.340058145 */, 16 }, + /* 1825 */ { MAD_F(0x0571e57d) /* 0.340306748 */, 16 }, + /* 1826 */ { MAD_F(0x0572ea37) /* 0.340555397 */, 16 }, + /* 1827 */ { MAD_F(0x0573eefd) /* 0.340804091 */, 16 }, + /* 1828 */ { MAD_F(0x0574f3d0) /* 0.341052830 */, 16 }, + /* 1829 */ { MAD_F(0x0575f8ae) /* 0.341301615 */, 16 }, + /* 1830 */ { MAD_F(0x0576fd99) /* 0.341550445 */, 16 }, + /* 1831 */ { MAD_F(0x05780290) /* 0.341799321 */, 16 }, + /* 1832 */ { MAD_F(0x05790793) /* 0.342048241 */, 16 }, + /* 1833 */ { MAD_F(0x057a0ca3) /* 0.342297207 */, 16 }, + /* 1834 */ { MAD_F(0x057b11be) /* 0.342546219 */, 16 }, + /* 1835 */ { MAD_F(0x057c16e6) /* 0.342795275 */, 16 }, + /* 1836 */ { MAD_F(0x057d1c1a) /* 0.343044377 */, 16 }, + /* 1837 */ { MAD_F(0x057e2159) /* 0.343293524 */, 16 }, + /* 1838 */ { MAD_F(0x057f26a6) /* 0.343542717 */, 16 }, + /* 1839 */ { MAD_F(0x05802bfe) /* 0.343791954 */, 16 }, + + /* 1840 */ { MAD_F(0x05813162) /* 0.344041237 */, 16 }, + /* 1841 */ { MAD_F(0x058236d2) /* 0.344290564 */, 16 }, + /* 1842 */ { MAD_F(0x05833c4f) /* 0.344539937 */, 16 }, + /* 1843 */ { MAD_F(0x058441d8) /* 0.344789356 */, 16 }, + /* 1844 */ { MAD_F(0x0585476c) /* 0.345038819 */, 16 }, + /* 1845 */ { MAD_F(0x05864d0d) /* 0.345288327 */, 16 }, + /* 1846 */ { MAD_F(0x058752ba) /* 0.345537880 */, 16 }, + /* 1847 */ { MAD_F(0x05885873) /* 0.345787479 */, 16 }, + /* 1848 */ { MAD_F(0x05895e39) /* 0.346037122 */, 16 }, + /* 1849 */ { MAD_F(0x058a640a) /* 0.346286811 */, 16 }, + /* 1850 */ { MAD_F(0x058b69e7) /* 0.346536545 */, 16 }, + /* 1851 */ { MAD_F(0x058c6fd1) /* 0.346786323 */, 16 }, + /* 1852 */ { MAD_F(0x058d75c6) /* 0.347036147 */, 16 }, + /* 1853 */ { MAD_F(0x058e7bc8) /* 0.347286015 */, 16 }, + /* 1854 */ { MAD_F(0x058f81d5) /* 0.347535929 */, 16 }, + /* 1855 */ { MAD_F(0x059087ef) /* 0.347785887 */, 16 }, + + /* 1856 */ { MAD_F(0x05918e15) /* 0.348035890 */, 16 }, + /* 1857 */ { MAD_F(0x05929447) /* 0.348285939 */, 16 }, + /* 1858 */ { MAD_F(0x05939a84) /* 0.348536032 */, 16 }, + /* 1859 */ { MAD_F(0x0594a0ce) /* 0.348786170 */, 16 }, + /* 1860 */ { MAD_F(0x0595a724) /* 0.349036353 */, 16 }, + /* 1861 */ { MAD_F(0x0596ad86) /* 0.349286580 */, 16 }, + /* 1862 */ { MAD_F(0x0597b3f4) /* 0.349536853 */, 16 }, + /* 1863 */ { MAD_F(0x0598ba6e) /* 0.349787170 */, 16 }, + /* 1864 */ { MAD_F(0x0599c0f4) /* 0.350037532 */, 16 }, + /* 1865 */ { MAD_F(0x059ac786) /* 0.350287939 */, 16 }, + /* 1866 */ { MAD_F(0x059bce25) /* 0.350538391 */, 16 }, + /* 1867 */ { MAD_F(0x059cd4cf) /* 0.350788887 */, 16 }, + /* 1868 */ { MAD_F(0x059ddb85) /* 0.351039428 */, 16 }, + /* 1869 */ { MAD_F(0x059ee247) /* 0.351290014 */, 16 }, + /* 1870 */ { MAD_F(0x059fe915) /* 0.351540645 */, 16 }, + /* 1871 */ { MAD_F(0x05a0efef) /* 0.351791320 */, 16 }, + + /* 1872 */ { MAD_F(0x05a1f6d5) /* 0.352042040 */, 16 }, + /* 1873 */ { MAD_F(0x05a2fdc7) /* 0.352292804 */, 16 }, + /* 1874 */ { MAD_F(0x05a404c5) /* 0.352543613 */, 16 }, + /* 1875 */ { MAD_F(0x05a50bcf) /* 0.352794467 */, 16 }, + /* 1876 */ { MAD_F(0x05a612e5) /* 0.353045365 */, 16 }, + /* 1877 */ { MAD_F(0x05a71a07) /* 0.353296308 */, 16 }, + /* 1878 */ { MAD_F(0x05a82135) /* 0.353547296 */, 16 }, + /* 1879 */ { MAD_F(0x05a9286f) /* 0.353798328 */, 16 }, + /* 1880 */ { MAD_F(0x05aa2fb5) /* 0.354049405 */, 16 }, + /* 1881 */ { MAD_F(0x05ab3707) /* 0.354300526 */, 16 }, + /* 1882 */ { MAD_F(0x05ac3e65) /* 0.354551691 */, 16 }, + /* 1883 */ { MAD_F(0x05ad45ce) /* 0.354802901 */, 16 }, + /* 1884 */ { MAD_F(0x05ae4d44) /* 0.355054156 */, 16 }, + /* 1885 */ { MAD_F(0x05af54c6) /* 0.355305455 */, 16 }, + /* 1886 */ { MAD_F(0x05b05c53) /* 0.355556799 */, 16 }, + /* 1887 */ { MAD_F(0x05b163ed) /* 0.355808187 */, 16 }, + + /* 1888 */ { MAD_F(0x05b26b92) /* 0.356059619 */, 16 }, + /* 1889 */ { MAD_F(0x05b37343) /* 0.356311096 */, 16 }, + /* 1890 */ { MAD_F(0x05b47b00) /* 0.356562617 */, 16 }, + /* 1891 */ { MAD_F(0x05b582c9) /* 0.356814182 */, 16 }, + /* 1892 */ { MAD_F(0x05b68a9e) /* 0.357065792 */, 16 }, + /* 1893 */ { MAD_F(0x05b7927f) /* 0.357317446 */, 16 }, + /* 1894 */ { MAD_F(0x05b89a6c) /* 0.357569145 */, 16 }, + /* 1895 */ { MAD_F(0x05b9a265) /* 0.357820887 */, 16 }, + /* 1896 */ { MAD_F(0x05baaa69) /* 0.358072674 */, 16 }, + /* 1897 */ { MAD_F(0x05bbb27a) /* 0.358324506 */, 16 }, + /* 1898 */ { MAD_F(0x05bcba96) /* 0.358576381 */, 16 }, + /* 1899 */ { MAD_F(0x05bdc2be) /* 0.358828301 */, 16 }, + /* 1900 */ { MAD_F(0x05becaf2) /* 0.359080265 */, 16 }, + /* 1901 */ { MAD_F(0x05bfd332) /* 0.359332273 */, 16 }, + /* 1902 */ { MAD_F(0x05c0db7e) /* 0.359584326 */, 16 }, + /* 1903 */ { MAD_F(0x05c1e3d6) /* 0.359836423 */, 16 }, + + /* 1904 */ { MAD_F(0x05c2ec39) /* 0.360088563 */, 16 }, + /* 1905 */ { MAD_F(0x05c3f4a9) /* 0.360340748 */, 16 }, + /* 1906 */ { MAD_F(0x05c4fd24) /* 0.360592977 */, 16 }, + /* 1907 */ { MAD_F(0x05c605ab) /* 0.360845251 */, 16 }, + /* 1908 */ { MAD_F(0x05c70e3e) /* 0.361097568 */, 16 }, + /* 1909 */ { MAD_F(0x05c816dd) /* 0.361349929 */, 16 }, + /* 1910 */ { MAD_F(0x05c91f87) /* 0.361602335 */, 16 }, + /* 1911 */ { MAD_F(0x05ca283e) /* 0.361854784 */, 16 }, + /* 1912 */ { MAD_F(0x05cb3100) /* 0.362107278 */, 16 }, + /* 1913 */ { MAD_F(0x05cc39ce) /* 0.362359815 */, 16 }, + /* 1914 */ { MAD_F(0x05cd42a8) /* 0.362612397 */, 16 }, + /* 1915 */ { MAD_F(0x05ce4b8d) /* 0.362865022 */, 16 }, + /* 1916 */ { MAD_F(0x05cf547f) /* 0.363117692 */, 16 }, + /* 1917 */ { MAD_F(0x05d05d7c) /* 0.363370405 */, 16 }, + /* 1918 */ { MAD_F(0x05d16685) /* 0.363623163 */, 16 }, + /* 1919 */ { MAD_F(0x05d26f9a) /* 0.363875964 */, 16 }, + + /* 1920 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 16 }, + /* 1921 */ { MAD_F(0x05d481e7) /* 0.364381698 */, 16 }, + /* 1922 */ { MAD_F(0x05d58b1f) /* 0.364634632 */, 16 }, + /* 1923 */ { MAD_F(0x05d69463) /* 0.364887608 */, 16 }, + /* 1924 */ { MAD_F(0x05d79db3) /* 0.365140629 */, 16 }, + /* 1925 */ { MAD_F(0x05d8a70f) /* 0.365393694 */, 16 }, + /* 1926 */ { MAD_F(0x05d9b076) /* 0.365646802 */, 16 }, + /* 1927 */ { MAD_F(0x05dab9e9) /* 0.365899955 */, 16 }, + /* 1928 */ { MAD_F(0x05dbc368) /* 0.366153151 */, 16 }, + /* 1929 */ { MAD_F(0x05dcccf2) /* 0.366406390 */, 16 }, + /* 1930 */ { MAD_F(0x05ddd689) /* 0.366659674 */, 16 }, + /* 1931 */ { MAD_F(0x05dee02b) /* 0.366913001 */, 16 }, + /* 1932 */ { MAD_F(0x05dfe9d8) /* 0.367166372 */, 16 }, + /* 1933 */ { MAD_F(0x05e0f392) /* 0.367419787 */, 16 }, + /* 1934 */ { MAD_F(0x05e1fd57) /* 0.367673246 */, 16 }, + /* 1935 */ { MAD_F(0x05e30728) /* 0.367926748 */, 16 }, + + /* 1936 */ { MAD_F(0x05e41105) /* 0.368180294 */, 16 }, + /* 1937 */ { MAD_F(0x05e51aed) /* 0.368433883 */, 16 }, + /* 1938 */ { MAD_F(0x05e624e1) /* 0.368687517 */, 16 }, + /* 1939 */ { MAD_F(0x05e72ee1) /* 0.368941193 */, 16 }, + /* 1940 */ { MAD_F(0x05e838ed) /* 0.369194914 */, 16 }, + /* 1941 */ { MAD_F(0x05e94304) /* 0.369448678 */, 16 }, + /* 1942 */ { MAD_F(0x05ea4d27) /* 0.369702485 */, 16 }, + /* 1943 */ { MAD_F(0x05eb5756) /* 0.369956336 */, 16 }, + /* 1944 */ { MAD_F(0x05ec6190) /* 0.370210231 */, 16 }, + /* 1945 */ { MAD_F(0x05ed6bd6) /* 0.370464169 */, 16 }, + /* 1946 */ { MAD_F(0x05ee7628) /* 0.370718151 */, 16 }, + /* 1947 */ { MAD_F(0x05ef8085) /* 0.370972177 */, 16 }, + /* 1948 */ { MAD_F(0x05f08aee) /* 0.371226245 */, 16 }, + /* 1949 */ { MAD_F(0x05f19563) /* 0.371480358 */, 16 }, + /* 1950 */ { MAD_F(0x05f29fe3) /* 0.371734513 */, 16 }, + /* 1951 */ { MAD_F(0x05f3aa6f) /* 0.371988712 */, 16 }, + + /* 1952 */ { MAD_F(0x05f4b507) /* 0.372242955 */, 16 }, + /* 1953 */ { MAD_F(0x05f5bfab) /* 0.372497241 */, 16 }, + /* 1954 */ { MAD_F(0x05f6ca5a) /* 0.372751570 */, 16 }, + /* 1955 */ { MAD_F(0x05f7d514) /* 0.373005943 */, 16 }, + /* 1956 */ { MAD_F(0x05f8dfdb) /* 0.373260359 */, 16 }, + /* 1957 */ { MAD_F(0x05f9eaad) /* 0.373514819 */, 16 }, + /* 1958 */ { MAD_F(0x05faf58a) /* 0.373769322 */, 16 }, + /* 1959 */ { MAD_F(0x05fc0073) /* 0.374023868 */, 16 }, + /* 1960 */ { MAD_F(0x05fd0b68) /* 0.374278458 */, 16 }, + /* 1961 */ { MAD_F(0x05fe1669) /* 0.374533091 */, 16 }, + /* 1962 */ { MAD_F(0x05ff2175) /* 0.374787767 */, 16 }, + /* 1963 */ { MAD_F(0x06002c8d) /* 0.375042486 */, 16 }, + /* 1964 */ { MAD_F(0x060137b0) /* 0.375297249 */, 16 }, + /* 1965 */ { MAD_F(0x060242df) /* 0.375552055 */, 16 }, + /* 1966 */ { MAD_F(0x06034e19) /* 0.375806904 */, 16 }, + /* 1967 */ { MAD_F(0x0604595f) /* 0.376061796 */, 16 }, + + /* 1968 */ { MAD_F(0x060564b1) /* 0.376316732 */, 16 }, + /* 1969 */ { MAD_F(0x0606700f) /* 0.376571710 */, 16 }, + /* 1970 */ { MAD_F(0x06077b77) /* 0.376826732 */, 16 }, + /* 1971 */ { MAD_F(0x060886ec) /* 0.377081797 */, 16 }, + /* 1972 */ { MAD_F(0x0609926c) /* 0.377336905 */, 16 }, + /* 1973 */ { MAD_F(0x060a9df8) /* 0.377592057 */, 16 }, + /* 1974 */ { MAD_F(0x060ba98f) /* 0.377847251 */, 16 }, + /* 1975 */ { MAD_F(0x060cb532) /* 0.378102489 */, 16 }, + /* 1976 */ { MAD_F(0x060dc0e0) /* 0.378357769 */, 16 }, + /* 1977 */ { MAD_F(0x060ecc9a) /* 0.378613093 */, 16 }, + /* 1978 */ { MAD_F(0x060fd860) /* 0.378868460 */, 16 }, + /* 1979 */ { MAD_F(0x0610e431) /* 0.379123870 */, 16 }, + /* 1980 */ { MAD_F(0x0611f00d) /* 0.379379322 */, 16 }, + /* 1981 */ { MAD_F(0x0612fbf5) /* 0.379634818 */, 16 }, + /* 1982 */ { MAD_F(0x061407e9) /* 0.379890357 */, 16 }, + /* 1983 */ { MAD_F(0x061513e8) /* 0.380145939 */, 16 }, + + /* 1984 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 16 }, + /* 1985 */ { MAD_F(0x06172c09) /* 0.380657231 */, 16 }, + /* 1986 */ { MAD_F(0x0618382b) /* 0.380912942 */, 16 }, + /* 1987 */ { MAD_F(0x06194458) /* 0.381168695 */, 16 }, + /* 1988 */ { MAD_F(0x061a5091) /* 0.381424492 */, 16 }, + /* 1989 */ { MAD_F(0x061b5cd5) /* 0.381680331 */, 16 }, + /* 1990 */ { MAD_F(0x061c6925) /* 0.381936213 */, 16 }, + /* 1991 */ { MAD_F(0x061d7581) /* 0.382192138 */, 16 }, + /* 1992 */ { MAD_F(0x061e81e8) /* 0.382448106 */, 16 }, + /* 1993 */ { MAD_F(0x061f8e5a) /* 0.382704117 */, 16 }, + /* 1994 */ { MAD_F(0x06209ad8) /* 0.382960171 */, 16 }, + /* 1995 */ { MAD_F(0x0621a761) /* 0.383216267 */, 16 }, + /* 1996 */ { MAD_F(0x0622b3f6) /* 0.383472406 */, 16 }, + /* 1997 */ { MAD_F(0x0623c096) /* 0.383728588 */, 16 }, + /* 1998 */ { MAD_F(0x0624cd42) /* 0.383984813 */, 16 }, + /* 1999 */ { MAD_F(0x0625d9f9) /* 0.384241080 */, 16 }, + + /* 2000 */ { MAD_F(0x0626e6bc) /* 0.384497391 */, 16 }, + /* 2001 */ { MAD_F(0x0627f38a) /* 0.384753744 */, 16 }, + /* 2002 */ { MAD_F(0x06290064) /* 0.385010139 */, 16 }, + /* 2003 */ { MAD_F(0x062a0d49) /* 0.385266578 */, 16 }, + /* 2004 */ { MAD_F(0x062b1a3a) /* 0.385523059 */, 16 }, + /* 2005 */ { MAD_F(0x062c2736) /* 0.385779582 */, 16 }, + /* 2006 */ { MAD_F(0x062d343d) /* 0.386036149 */, 16 }, + /* 2007 */ { MAD_F(0x062e4150) /* 0.386292758 */, 16 }, + /* 2008 */ { MAD_F(0x062f4e6f) /* 0.386549409 */, 16 }, + /* 2009 */ { MAD_F(0x06305b99) /* 0.386806104 */, 16 }, + /* 2010 */ { MAD_F(0x063168ce) /* 0.387062840 */, 16 }, + /* 2011 */ { MAD_F(0x0632760f) /* 0.387319620 */, 16 }, + /* 2012 */ { MAD_F(0x0633835b) /* 0.387576442 */, 16 }, + /* 2013 */ { MAD_F(0x063490b2) /* 0.387833306 */, 16 }, + /* 2014 */ { MAD_F(0x06359e15) /* 0.388090213 */, 16 }, + /* 2015 */ { MAD_F(0x0636ab83) /* 0.388347163 */, 16 }, + + /* 2016 */ { MAD_F(0x0637b8fd) /* 0.388604155 */, 16 }, + /* 2017 */ { MAD_F(0x0638c682) /* 0.388861190 */, 16 }, + /* 2018 */ { MAD_F(0x0639d413) /* 0.389118267 */, 16 }, + /* 2019 */ { MAD_F(0x063ae1af) /* 0.389375386 */, 16 }, + /* 2020 */ { MAD_F(0x063bef56) /* 0.389632548 */, 16 }, + /* 2021 */ { MAD_F(0x063cfd09) /* 0.389889752 */, 16 }, + /* 2022 */ { MAD_F(0x063e0ac7) /* 0.390146999 */, 16 }, + /* 2023 */ { MAD_F(0x063f1891) /* 0.390404289 */, 16 }, + /* 2024 */ { MAD_F(0x06402666) /* 0.390661620 */, 16 }, + /* 2025 */ { MAD_F(0x06413446) /* 0.390918994 */, 16 }, + /* 2026 */ { MAD_F(0x06424232) /* 0.391176411 */, 16 }, + /* 2027 */ { MAD_F(0x06435029) /* 0.391433869 */, 16 }, + /* 2028 */ { MAD_F(0x06445e2b) /* 0.391691371 */, 16 }, + /* 2029 */ { MAD_F(0x06456c39) /* 0.391948914 */, 16 }, + /* 2030 */ { MAD_F(0x06467a52) /* 0.392206500 */, 16 }, + /* 2031 */ { MAD_F(0x06478877) /* 0.392464128 */, 16 }, + + /* 2032 */ { MAD_F(0x064896a7) /* 0.392721798 */, 16 }, + /* 2033 */ { MAD_F(0x0649a4e2) /* 0.392979511 */, 16 }, + /* 2034 */ { MAD_F(0x064ab328) /* 0.393237266 */, 16 }, + /* 2035 */ { MAD_F(0x064bc17a) /* 0.393495063 */, 16 }, + /* 2036 */ { MAD_F(0x064ccfd8) /* 0.393752902 */, 16 }, + /* 2037 */ { MAD_F(0x064dde40) /* 0.394010784 */, 16 }, + /* 2038 */ { MAD_F(0x064eecb4) /* 0.394268707 */, 16 }, + /* 2039 */ { MAD_F(0x064ffb33) /* 0.394526673 */, 16 }, + /* 2040 */ { MAD_F(0x065109be) /* 0.394784681 */, 16 }, + /* 2041 */ { MAD_F(0x06521854) /* 0.395042732 */, 16 }, + /* 2042 */ { MAD_F(0x065326f5) /* 0.395300824 */, 16 }, + /* 2043 */ { MAD_F(0x065435a1) /* 0.395558959 */, 16 }, + /* 2044 */ { MAD_F(0x06554459) /* 0.395817135 */, 16 }, + /* 2045 */ { MAD_F(0x0656531c) /* 0.396075354 */, 16 }, + /* 2046 */ { MAD_F(0x065761ea) /* 0.396333615 */, 16 }, + /* 2047 */ { MAD_F(0x065870c4) /* 0.396591918 */, 16 }, + + /* 2048 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 16 }, + /* 2049 */ { MAD_F(0x065a8e99) /* 0.397108650 */, 16 }, + /* 2050 */ { MAD_F(0x065b9d95) /* 0.397367079 */, 16 }, + /* 2051 */ { MAD_F(0x065cac9c) /* 0.397625550 */, 16 }, + /* 2052 */ { MAD_F(0x065dbbae) /* 0.397884063 */, 16 }, + /* 2053 */ { MAD_F(0x065ecacb) /* 0.398142619 */, 16 }, + /* 2054 */ { MAD_F(0x065fd9f4) /* 0.398401216 */, 16 }, + /* 2055 */ { MAD_F(0x0660e928) /* 0.398659855 */, 16 }, + /* 2056 */ { MAD_F(0x0661f867) /* 0.398918536 */, 16 }, + /* 2057 */ { MAD_F(0x066307b1) /* 0.399177259 */, 16 }, + /* 2058 */ { MAD_F(0x06641707) /* 0.399436024 */, 16 }, + /* 2059 */ { MAD_F(0x06652668) /* 0.399694831 */, 16 }, + /* 2060 */ { MAD_F(0x066635d4) /* 0.399953679 */, 16 }, + /* 2061 */ { MAD_F(0x0667454c) /* 0.400212570 */, 16 }, + /* 2062 */ { MAD_F(0x066854ce) /* 0.400471503 */, 16 }, + /* 2063 */ { MAD_F(0x0669645c) /* 0.400730477 */, 16 }, + + /* 2064 */ { MAD_F(0x066a73f5) /* 0.400989493 */, 16 }, + /* 2065 */ { MAD_F(0x066b839a) /* 0.401248551 */, 16 }, + /* 2066 */ { MAD_F(0x066c9349) /* 0.401507651 */, 16 }, + /* 2067 */ { MAD_F(0x066da304) /* 0.401766793 */, 16 }, + /* 2068 */ { MAD_F(0x066eb2ca) /* 0.402025976 */, 16 }, + /* 2069 */ { MAD_F(0x066fc29b) /* 0.402285202 */, 16 }, + /* 2070 */ { MAD_F(0x0670d278) /* 0.402544469 */, 16 }, + /* 2071 */ { MAD_F(0x0671e25f) /* 0.402803777 */, 16 }, + /* 2072 */ { MAD_F(0x0672f252) /* 0.403063128 */, 16 }, + /* 2073 */ { MAD_F(0x06740250) /* 0.403322520 */, 16 }, + /* 2074 */ { MAD_F(0x0675125a) /* 0.403581954 */, 16 }, + /* 2075 */ { MAD_F(0x0676226e) /* 0.403841430 */, 16 }, + /* 2076 */ { MAD_F(0x0677328e) /* 0.404100947 */, 16 }, + /* 2077 */ { MAD_F(0x067842b9) /* 0.404360506 */, 16 }, + /* 2078 */ { MAD_F(0x067952ef) /* 0.404620107 */, 16 }, + /* 2079 */ { MAD_F(0x067a6330) /* 0.404879749 */, 16 }, + + /* 2080 */ { MAD_F(0x067b737c) /* 0.405139433 */, 16 }, + /* 2081 */ { MAD_F(0x067c83d4) /* 0.405399159 */, 16 }, + /* 2082 */ { MAD_F(0x067d9436) /* 0.405658926 */, 16 }, + /* 2083 */ { MAD_F(0x067ea4a4) /* 0.405918735 */, 16 }, + /* 2084 */ { MAD_F(0x067fb51d) /* 0.406178585 */, 16 }, + /* 2085 */ { MAD_F(0x0680c5a2) /* 0.406438477 */, 16 }, + /* 2086 */ { MAD_F(0x0681d631) /* 0.406698410 */, 16 }, + /* 2087 */ { MAD_F(0x0682e6cb) /* 0.406958385 */, 16 }, + /* 2088 */ { MAD_F(0x0683f771) /* 0.407218402 */, 16 }, + /* 2089 */ { MAD_F(0x06850822) /* 0.407478460 */, 16 }, + /* 2090 */ { MAD_F(0x068618de) /* 0.407738559 */, 16 }, + /* 2091 */ { MAD_F(0x068729a5) /* 0.407998700 */, 16 }, + /* 2092 */ { MAD_F(0x06883a77) /* 0.408258883 */, 16 }, + /* 2093 */ { MAD_F(0x06894b55) /* 0.408519107 */, 16 }, + /* 2094 */ { MAD_F(0x068a5c3d) /* 0.408779372 */, 16 }, + /* 2095 */ { MAD_F(0x068b6d31) /* 0.409039679 */, 16 }, + + /* 2096 */ { MAD_F(0x068c7e2f) /* 0.409300027 */, 16 }, + /* 2097 */ { MAD_F(0x068d8f39) /* 0.409560417 */, 16 }, + /* 2098 */ { MAD_F(0x068ea04e) /* 0.409820848 */, 16 }, + /* 2099 */ { MAD_F(0x068fb16e) /* 0.410081321 */, 16 }, + /* 2100 */ { MAD_F(0x0690c299) /* 0.410341834 */, 16 }, + /* 2101 */ { MAD_F(0x0691d3cf) /* 0.410602390 */, 16 }, + /* 2102 */ { MAD_F(0x0692e511) /* 0.410862986 */, 16 }, + /* 2103 */ { MAD_F(0x0693f65d) /* 0.411123624 */, 16 }, + /* 2104 */ { MAD_F(0x069507b5) /* 0.411384303 */, 16 }, + /* 2105 */ { MAD_F(0x06961917) /* 0.411645024 */, 16 }, + /* 2106 */ { MAD_F(0x06972a85) /* 0.411905785 */, 16 }, + /* 2107 */ { MAD_F(0x06983bfe) /* 0.412166588 */, 16 }, + /* 2108 */ { MAD_F(0x06994d82) /* 0.412427433 */, 16 }, + /* 2109 */ { MAD_F(0x069a5f11) /* 0.412688318 */, 16 }, + /* 2110 */ { MAD_F(0x069b70ab) /* 0.412949245 */, 16 }, + /* 2111 */ { MAD_F(0x069c8250) /* 0.413210213 */, 16 }, + + /* 2112 */ { MAD_F(0x069d9400) /* 0.413471222 */, 16 }, + /* 2113 */ { MAD_F(0x069ea5bb) /* 0.413732273 */, 16 }, + /* 2114 */ { MAD_F(0x069fb781) /* 0.413993364 */, 16 }, + /* 2115 */ { MAD_F(0x06a0c953) /* 0.414254497 */, 16 }, + /* 2116 */ { MAD_F(0x06a1db2f) /* 0.414515671 */, 16 }, + /* 2117 */ { MAD_F(0x06a2ed16) /* 0.414776886 */, 16 }, + /* 2118 */ { MAD_F(0x06a3ff09) /* 0.415038142 */, 16 }, + /* 2119 */ { MAD_F(0x06a51106) /* 0.415299440 */, 16 }, + /* 2120 */ { MAD_F(0x06a6230f) /* 0.415560778 */, 16 }, + /* 2121 */ { MAD_F(0x06a73522) /* 0.415822157 */, 16 }, + /* 2122 */ { MAD_F(0x06a84741) /* 0.416083578 */, 16 }, + /* 2123 */ { MAD_F(0x06a9596a) /* 0.416345040 */, 16 }, + /* 2124 */ { MAD_F(0x06aa6b9f) /* 0.416606542 */, 16 }, + /* 2125 */ { MAD_F(0x06ab7ddf) /* 0.416868086 */, 16 }, + /* 2126 */ { MAD_F(0x06ac9029) /* 0.417129671 */, 16 }, + /* 2127 */ { MAD_F(0x06ada27f) /* 0.417391297 */, 16 }, + + /* 2128 */ { MAD_F(0x06aeb4e0) /* 0.417652964 */, 16 }, + /* 2129 */ { MAD_F(0x06afc74b) /* 0.417914672 */, 16 }, + /* 2130 */ { MAD_F(0x06b0d9c2) /* 0.418176420 */, 16 }, + /* 2131 */ { MAD_F(0x06b1ec43) /* 0.418438210 */, 16 }, + /* 2132 */ { MAD_F(0x06b2fed0) /* 0.418700041 */, 16 }, + /* 2133 */ { MAD_F(0x06b41168) /* 0.418961912 */, 16 }, + /* 2134 */ { MAD_F(0x06b5240a) /* 0.419223825 */, 16 }, + /* 2135 */ { MAD_F(0x06b636b8) /* 0.419485778 */, 16 }, + /* 2136 */ { MAD_F(0x06b74971) /* 0.419747773 */, 16 }, + /* 2137 */ { MAD_F(0x06b85c34) /* 0.420009808 */, 16 }, + /* 2138 */ { MAD_F(0x06b96f03) /* 0.420271884 */, 16 }, + /* 2139 */ { MAD_F(0x06ba81dc) /* 0.420534001 */, 16 }, + /* 2140 */ { MAD_F(0x06bb94c1) /* 0.420796159 */, 16 }, + /* 2141 */ { MAD_F(0x06bca7b0) /* 0.421058358 */, 16 }, + /* 2142 */ { MAD_F(0x06bdbaaa) /* 0.421320597 */, 16 }, + /* 2143 */ { MAD_F(0x06becdb0) /* 0.421582878 */, 16 }, + + /* 2144 */ { MAD_F(0x06bfe0c0) /* 0.421845199 */, 16 }, + /* 2145 */ { MAD_F(0x06c0f3db) /* 0.422107561 */, 16 }, + /* 2146 */ { MAD_F(0x06c20702) /* 0.422369964 */, 16 }, + /* 2147 */ { MAD_F(0x06c31a33) /* 0.422632407 */, 16 }, + /* 2148 */ { MAD_F(0x06c42d6f) /* 0.422894891 */, 16 }, + /* 2149 */ { MAD_F(0x06c540b6) /* 0.423157416 */, 16 }, + /* 2150 */ { MAD_F(0x06c65408) /* 0.423419982 */, 16 }, + /* 2151 */ { MAD_F(0x06c76765) /* 0.423682588 */, 16 }, + /* 2152 */ { MAD_F(0x06c87acc) /* 0.423945235 */, 16 }, + /* 2153 */ { MAD_F(0x06c98e3f) /* 0.424207923 */, 16 }, + /* 2154 */ { MAD_F(0x06caa1bd) /* 0.424470652 */, 16 }, + /* 2155 */ { MAD_F(0x06cbb545) /* 0.424733421 */, 16 }, + /* 2156 */ { MAD_F(0x06ccc8d9) /* 0.424996230 */, 16 }, + /* 2157 */ { MAD_F(0x06cddc77) /* 0.425259081 */, 16 }, + /* 2158 */ { MAD_F(0x06cef020) /* 0.425521972 */, 16 }, + /* 2159 */ { MAD_F(0x06d003d4) /* 0.425784903 */, 16 }, + + /* 2160 */ { MAD_F(0x06d11794) /* 0.426047876 */, 16 }, + /* 2161 */ { MAD_F(0x06d22b5e) /* 0.426310889 */, 16 }, + /* 2162 */ { MAD_F(0x06d33f32) /* 0.426573942 */, 16 }, + /* 2163 */ { MAD_F(0x06d45312) /* 0.426837036 */, 16 }, + /* 2164 */ { MAD_F(0x06d566fd) /* 0.427100170 */, 16 }, + /* 2165 */ { MAD_F(0x06d67af2) /* 0.427363345 */, 16 }, + /* 2166 */ { MAD_F(0x06d78ef3) /* 0.427626561 */, 16 }, + /* 2167 */ { MAD_F(0x06d8a2fe) /* 0.427889817 */, 16 }, + /* 2168 */ { MAD_F(0x06d9b714) /* 0.428153114 */, 16 }, + /* 2169 */ { MAD_F(0x06dacb35) /* 0.428416451 */, 16 }, + /* 2170 */ { MAD_F(0x06dbdf61) /* 0.428679828 */, 16 }, + /* 2171 */ { MAD_F(0x06dcf398) /* 0.428943246 */, 16 }, + /* 2172 */ { MAD_F(0x06de07d9) /* 0.429206704 */, 16 }, + /* 2173 */ { MAD_F(0x06df1c26) /* 0.429470203 */, 16 }, + /* 2174 */ { MAD_F(0x06e0307d) /* 0.429733743 */, 16 }, + /* 2175 */ { MAD_F(0x06e144df) /* 0.429997322 */, 16 }, + + /* 2176 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 16 }, + /* 2177 */ { MAD_F(0x06e36dc4) /* 0.430524603 */, 16 }, + /* 2178 */ { MAD_F(0x06e48246) /* 0.430788304 */, 16 }, + /* 2179 */ { MAD_F(0x06e596d4) /* 0.431052045 */, 16 }, + /* 2180 */ { MAD_F(0x06e6ab6c) /* 0.431315826 */, 16 }, + /* 2181 */ { MAD_F(0x06e7c00f) /* 0.431579648 */, 16 }, + /* 2182 */ { MAD_F(0x06e8d4bd) /* 0.431843511 */, 16 }, + /* 2183 */ { MAD_F(0x06e9e976) /* 0.432107413 */, 16 }, + /* 2184 */ { MAD_F(0x06eafe3a) /* 0.432371356 */, 16 }, + /* 2185 */ { MAD_F(0x06ec1308) /* 0.432635339 */, 16 }, + /* 2186 */ { MAD_F(0x06ed27e2) /* 0.432899362 */, 16 }, + /* 2187 */ { MAD_F(0x06ee3cc6) /* 0.433163426 */, 16 }, + /* 2188 */ { MAD_F(0x06ef51b4) /* 0.433427530 */, 16 }, + /* 2189 */ { MAD_F(0x06f066ae) /* 0.433691674 */, 16 }, + /* 2190 */ { MAD_F(0x06f17bb3) /* 0.433955859 */, 16 }, + /* 2191 */ { MAD_F(0x06f290c2) /* 0.434220083 */, 16 }, + + /* 2192 */ { MAD_F(0x06f3a5dc) /* 0.434484348 */, 16 }, + /* 2193 */ { MAD_F(0x06f4bb01) /* 0.434748653 */, 16 }, + /* 2194 */ { MAD_F(0x06f5d030) /* 0.435012998 */, 16 }, + /* 2195 */ { MAD_F(0x06f6e56b) /* 0.435277383 */, 16 }, + /* 2196 */ { MAD_F(0x06f7fab0) /* 0.435541809 */, 16 }, + /* 2197 */ { MAD_F(0x06f91000) /* 0.435806274 */, 16 }, + /* 2198 */ { MAD_F(0x06fa255a) /* 0.436070780 */, 16 }, + /* 2199 */ { MAD_F(0x06fb3ac0) /* 0.436335326 */, 16 }, + /* 2200 */ { MAD_F(0x06fc5030) /* 0.436599912 */, 16 }, + /* 2201 */ { MAD_F(0x06fd65ab) /* 0.436864538 */, 16 }, + /* 2202 */ { MAD_F(0x06fe7b31) /* 0.437129204 */, 16 }, + /* 2203 */ { MAD_F(0x06ff90c2) /* 0.437393910 */, 16 }, + /* 2204 */ { MAD_F(0x0700a65d) /* 0.437658657 */, 16 }, + /* 2205 */ { MAD_F(0x0701bc03) /* 0.437923443 */, 16 }, + /* 2206 */ { MAD_F(0x0702d1b4) /* 0.438188269 */, 16 }, + /* 2207 */ { MAD_F(0x0703e76f) /* 0.438453136 */, 16 }, + + /* 2208 */ { MAD_F(0x0704fd35) /* 0.438718042 */, 16 }, + /* 2209 */ { MAD_F(0x07061306) /* 0.438982988 */, 16 }, + /* 2210 */ { MAD_F(0x070728e2) /* 0.439247975 */, 16 }, + /* 2211 */ { MAD_F(0x07083ec9) /* 0.439513001 */, 16 }, + /* 2212 */ { MAD_F(0x070954ba) /* 0.439778067 */, 16 }, + /* 2213 */ { MAD_F(0x070a6ab6) /* 0.440043173 */, 16 }, + /* 2214 */ { MAD_F(0x070b80bc) /* 0.440308320 */, 16 }, + /* 2215 */ { MAD_F(0x070c96ce) /* 0.440573506 */, 16 }, + /* 2216 */ { MAD_F(0x070dacea) /* 0.440838732 */, 16 }, + /* 2217 */ { MAD_F(0x070ec310) /* 0.441103997 */, 16 }, + /* 2218 */ { MAD_F(0x070fd942) /* 0.441369303 */, 16 }, + /* 2219 */ { MAD_F(0x0710ef7e) /* 0.441634649 */, 16 }, + /* 2220 */ { MAD_F(0x071205c5) /* 0.441900034 */, 16 }, + /* 2221 */ { MAD_F(0x07131c17) /* 0.442165460 */, 16 }, + /* 2222 */ { MAD_F(0x07143273) /* 0.442430925 */, 16 }, + /* 2223 */ { MAD_F(0x071548da) /* 0.442696430 */, 16 }, + + /* 2224 */ { MAD_F(0x07165f4b) /* 0.442961975 */, 16 }, + /* 2225 */ { MAD_F(0x071775c8) /* 0.443227559 */, 16 }, + /* 2226 */ { MAD_F(0x07188c4f) /* 0.443493184 */, 16 }, + /* 2227 */ { MAD_F(0x0719a2e0) /* 0.443758848 */, 16 }, + /* 2228 */ { MAD_F(0x071ab97d) /* 0.444024552 */, 16 }, + /* 2229 */ { MAD_F(0x071bd024) /* 0.444290296 */, 16 }, + /* 2230 */ { MAD_F(0x071ce6d6) /* 0.444556079 */, 16 }, + /* 2231 */ { MAD_F(0x071dfd92) /* 0.444821902 */, 16 }, + /* 2232 */ { MAD_F(0x071f1459) /* 0.445087765 */, 16 }, + /* 2233 */ { MAD_F(0x07202b2b) /* 0.445353668 */, 16 }, + /* 2234 */ { MAD_F(0x07214207) /* 0.445619610 */, 16 }, + /* 2235 */ { MAD_F(0x072258ee) /* 0.445885592 */, 16 }, + /* 2236 */ { MAD_F(0x07236fe0) /* 0.446151614 */, 16 }, + /* 2237 */ { MAD_F(0x072486dc) /* 0.446417675 */, 16 }, + /* 2238 */ { MAD_F(0x07259de3) /* 0.446683776 */, 16 }, + /* 2239 */ { MAD_F(0x0726b4f4) /* 0.446949917 */, 16 }, + + /* 2240 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 16 }, + /* 2241 */ { MAD_F(0x0728e338) /* 0.447482317 */, 16 }, + /* 2242 */ { MAD_F(0x0729fa69) /* 0.447748576 */, 16 }, + /* 2243 */ { MAD_F(0x072b11a5) /* 0.448014875 */, 16 }, + /* 2244 */ { MAD_F(0x072c28ec) /* 0.448281214 */, 16 }, + /* 2245 */ { MAD_F(0x072d403d) /* 0.448547592 */, 16 }, + /* 2246 */ { MAD_F(0x072e5799) /* 0.448814010 */, 16 }, + /* 2247 */ { MAD_F(0x072f6f00) /* 0.449080467 */, 16 }, + /* 2248 */ { MAD_F(0x07308671) /* 0.449346964 */, 16 }, + /* 2249 */ { MAD_F(0x07319ded) /* 0.449613501 */, 16 }, + /* 2250 */ { MAD_F(0x0732b573) /* 0.449880076 */, 16 }, + /* 2251 */ { MAD_F(0x0733cd04) /* 0.450146692 */, 16 }, + /* 2252 */ { MAD_F(0x0734e4a0) /* 0.450413347 */, 16 }, + /* 2253 */ { MAD_F(0x0735fc46) /* 0.450680041 */, 16 }, + /* 2254 */ { MAD_F(0x073713f7) /* 0.450946775 */, 16 }, + /* 2255 */ { MAD_F(0x07382bb2) /* 0.451213548 */, 16 }, + + /* 2256 */ { MAD_F(0x07394378) /* 0.451480360 */, 16 }, + /* 2257 */ { MAD_F(0x073a5b49) /* 0.451747213 */, 16 }, + /* 2258 */ { MAD_F(0x073b7324) /* 0.452014104 */, 16 }, + /* 2259 */ { MAD_F(0x073c8b0a) /* 0.452281035 */, 16 }, + /* 2260 */ { MAD_F(0x073da2fa) /* 0.452548005 */, 16 }, + /* 2261 */ { MAD_F(0x073ebaf5) /* 0.452815015 */, 16 }, + /* 2262 */ { MAD_F(0x073fd2fa) /* 0.453082064 */, 16 }, + /* 2263 */ { MAD_F(0x0740eb0a) /* 0.453349152 */, 16 }, + /* 2264 */ { MAD_F(0x07420325) /* 0.453616280 */, 16 }, + /* 2265 */ { MAD_F(0x07431b4a) /* 0.453883447 */, 16 }, + /* 2266 */ { MAD_F(0x0744337a) /* 0.454150653 */, 16 }, + /* 2267 */ { MAD_F(0x07454bb4) /* 0.454417899 */, 16 }, + /* 2268 */ { MAD_F(0x074663f8) /* 0.454685184 */, 16 }, + /* 2269 */ { MAD_F(0x07477c48) /* 0.454952508 */, 16 }, + /* 2270 */ { MAD_F(0x074894a2) /* 0.455219872 */, 16 }, + /* 2271 */ { MAD_F(0x0749ad06) /* 0.455487275 */, 16 }, + + /* 2272 */ { MAD_F(0x074ac575) /* 0.455754717 */, 16 }, + /* 2273 */ { MAD_F(0x074bddee) /* 0.456022198 */, 16 }, + /* 2274 */ { MAD_F(0x074cf672) /* 0.456289719 */, 16 }, + /* 2275 */ { MAD_F(0x074e0f01) /* 0.456557278 */, 16 }, + /* 2276 */ { MAD_F(0x074f279a) /* 0.456824877 */, 16 }, + /* 2277 */ { MAD_F(0x0750403e) /* 0.457092516 */, 16 }, + /* 2278 */ { MAD_F(0x075158ec) /* 0.457360193 */, 16 }, + /* 2279 */ { MAD_F(0x075271a4) /* 0.457627909 */, 16 }, + /* 2280 */ { MAD_F(0x07538a67) /* 0.457895665 */, 16 }, + /* 2281 */ { MAD_F(0x0754a335) /* 0.458163460 */, 16 }, + /* 2282 */ { MAD_F(0x0755bc0d) /* 0.458431294 */, 16 }, + /* 2283 */ { MAD_F(0x0756d4f0) /* 0.458699167 */, 16 }, + /* 2284 */ { MAD_F(0x0757eddd) /* 0.458967079 */, 16 }, + /* 2285 */ { MAD_F(0x075906d5) /* 0.459235030 */, 16 }, + /* 2286 */ { MAD_F(0x075a1fd7) /* 0.459503021 */, 16 }, + /* 2287 */ { MAD_F(0x075b38e3) /* 0.459771050 */, 16 }, + + /* 2288 */ { MAD_F(0x075c51fa) /* 0.460039119 */, 16 }, + /* 2289 */ { MAD_F(0x075d6b1c) /* 0.460307226 */, 16 }, + /* 2290 */ { MAD_F(0x075e8448) /* 0.460575373 */, 16 }, + /* 2291 */ { MAD_F(0x075f9d7f) /* 0.460843559 */, 16 }, + /* 2292 */ { MAD_F(0x0760b6c0) /* 0.461111783 */, 16 }, + /* 2293 */ { MAD_F(0x0761d00b) /* 0.461380047 */, 16 }, + /* 2294 */ { MAD_F(0x0762e961) /* 0.461648350 */, 16 }, + /* 2295 */ { MAD_F(0x076402c1) /* 0.461916691 */, 16 }, + /* 2296 */ { MAD_F(0x07651c2c) /* 0.462185072 */, 16 }, + /* 2297 */ { MAD_F(0x076635a2) /* 0.462453492 */, 16 }, + /* 2298 */ { MAD_F(0x07674f22) /* 0.462721950 */, 16 }, + /* 2299 */ { MAD_F(0x076868ac) /* 0.462990448 */, 16 }, + /* 2300 */ { MAD_F(0x07698240) /* 0.463258984 */, 16 }, + /* 2301 */ { MAD_F(0x076a9be0) /* 0.463527560 */, 16 }, + /* 2302 */ { MAD_F(0x076bb589) /* 0.463796174 */, 16 }, + /* 2303 */ { MAD_F(0x076ccf3d) /* 0.464064827 */, 16 }, + + /* 2304 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 16 }, + /* 2305 */ { MAD_F(0x076f02c5) /* 0.464602250 */, 16 }, + /* 2306 */ { MAD_F(0x07701c98) /* 0.464871020 */, 16 }, + /* 2307 */ { MAD_F(0x07713676) /* 0.465139829 */, 16 }, + /* 2308 */ { MAD_F(0x0772505e) /* 0.465408676 */, 16 }, + /* 2309 */ { MAD_F(0x07736a51) /* 0.465677563 */, 16 }, + /* 2310 */ { MAD_F(0x0774844e) /* 0.465946488 */, 16 }, + /* 2311 */ { MAD_F(0x07759e55) /* 0.466215452 */, 16 }, + /* 2312 */ { MAD_F(0x0776b867) /* 0.466484455 */, 16 }, + /* 2313 */ { MAD_F(0x0777d283) /* 0.466753496 */, 16 }, + /* 2314 */ { MAD_F(0x0778ecaa) /* 0.467022577 */, 16 }, + /* 2315 */ { MAD_F(0x077a06db) /* 0.467291696 */, 16 }, + /* 2316 */ { MAD_F(0x077b2117) /* 0.467560854 */, 16 }, + /* 2317 */ { MAD_F(0x077c3b5d) /* 0.467830050 */, 16 }, + /* 2318 */ { MAD_F(0x077d55ad) /* 0.468099285 */, 16 }, + /* 2319 */ { MAD_F(0x077e7008) /* 0.468368560 */, 16 }, + + /* 2320 */ { MAD_F(0x077f8a6d) /* 0.468637872 */, 16 }, + /* 2321 */ { MAD_F(0x0780a4dc) /* 0.468907224 */, 16 }, + /* 2322 */ { MAD_F(0x0781bf56) /* 0.469176614 */, 16 }, + /* 2323 */ { MAD_F(0x0782d9da) /* 0.469446043 */, 16 }, + /* 2324 */ { MAD_F(0x0783f469) /* 0.469715510 */, 16 }, + /* 2325 */ { MAD_F(0x07850f02) /* 0.469985016 */, 16 }, + /* 2326 */ { MAD_F(0x078629a5) /* 0.470254561 */, 16 }, + /* 2327 */ { MAD_F(0x07874453) /* 0.470524145 */, 16 }, + /* 2328 */ { MAD_F(0x07885f0b) /* 0.470793767 */, 16 }, + /* 2329 */ { MAD_F(0x078979ce) /* 0.471063427 */, 16 }, + /* 2330 */ { MAD_F(0x078a949a) /* 0.471333126 */, 16 }, + /* 2331 */ { MAD_F(0x078baf72) /* 0.471602864 */, 16 }, + /* 2332 */ { MAD_F(0x078cca53) /* 0.471872641 */, 16 }, + /* 2333 */ { MAD_F(0x078de53f) /* 0.472142456 */, 16 }, + /* 2334 */ { MAD_F(0x078f0035) /* 0.472412309 */, 16 }, + /* 2335 */ { MAD_F(0x07901b36) /* 0.472682201 */, 16 }, + + /* 2336 */ { MAD_F(0x07913641) /* 0.472952132 */, 16 }, + /* 2337 */ { MAD_F(0x07925156) /* 0.473222101 */, 16 }, + /* 2338 */ { MAD_F(0x07936c76) /* 0.473492108 */, 16 }, + /* 2339 */ { MAD_F(0x079487a0) /* 0.473762155 */, 16 }, + /* 2340 */ { MAD_F(0x0795a2d4) /* 0.474032239 */, 16 }, + /* 2341 */ { MAD_F(0x0796be13) /* 0.474302362 */, 16 }, + /* 2342 */ { MAD_F(0x0797d95c) /* 0.474572524 */, 16 }, + /* 2343 */ { MAD_F(0x0798f4af) /* 0.474842724 */, 16 }, + /* 2344 */ { MAD_F(0x079a100c) /* 0.475112962 */, 16 }, + /* 2345 */ { MAD_F(0x079b2b74) /* 0.475383239 */, 16 }, + /* 2346 */ { MAD_F(0x079c46e7) /* 0.475653554 */, 16 }, + /* 2347 */ { MAD_F(0x079d6263) /* 0.475923908 */, 16 }, + /* 2348 */ { MAD_F(0x079e7dea) /* 0.476194300 */, 16 }, + /* 2349 */ { MAD_F(0x079f997b) /* 0.476464731 */, 16 }, + /* 2350 */ { MAD_F(0x07a0b516) /* 0.476735200 */, 16 }, + /* 2351 */ { MAD_F(0x07a1d0bc) /* 0.477005707 */, 16 }, + + /* 2352 */ { MAD_F(0x07a2ec6c) /* 0.477276252 */, 16 }, + /* 2353 */ { MAD_F(0x07a40827) /* 0.477546836 */, 16 }, + /* 2354 */ { MAD_F(0x07a523eb) /* 0.477817459 */, 16 }, + /* 2355 */ { MAD_F(0x07a63fba) /* 0.478088119 */, 16 }, + /* 2356 */ { MAD_F(0x07a75b93) /* 0.478358818 */, 16 }, + /* 2357 */ { MAD_F(0x07a87777) /* 0.478629555 */, 16 }, + /* 2358 */ { MAD_F(0x07a99364) /* 0.478900331 */, 16 }, + /* 2359 */ { MAD_F(0x07aaaf5c) /* 0.479171145 */, 16 }, + /* 2360 */ { MAD_F(0x07abcb5f) /* 0.479441997 */, 16 }, + /* 2361 */ { MAD_F(0x07ace76b) /* 0.479712887 */, 16 }, + /* 2362 */ { MAD_F(0x07ae0382) /* 0.479983816 */, 16 }, + /* 2363 */ { MAD_F(0x07af1fa3) /* 0.480254782 */, 16 }, + /* 2364 */ { MAD_F(0x07b03bcf) /* 0.480525787 */, 16 }, + /* 2365 */ { MAD_F(0x07b15804) /* 0.480796831 */, 16 }, + /* 2366 */ { MAD_F(0x07b27444) /* 0.481067912 */, 16 }, + /* 2367 */ { MAD_F(0x07b3908e) /* 0.481339032 */, 16 }, + + /* 2368 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 16 }, + /* 2369 */ { MAD_F(0x07b5c941) /* 0.481881385 */, 16 }, + /* 2370 */ { MAD_F(0x07b6e5aa) /* 0.482152620 */, 16 }, + /* 2371 */ { MAD_F(0x07b8021d) /* 0.482423892 */, 16 }, + /* 2372 */ { MAD_F(0x07b91e9b) /* 0.482695202 */, 16 }, + /* 2373 */ { MAD_F(0x07ba3b22) /* 0.482966551 */, 16 }, + /* 2374 */ { MAD_F(0x07bb57b4) /* 0.483237938 */, 16 }, + /* 2375 */ { MAD_F(0x07bc7450) /* 0.483509362 */, 16 }, + /* 2376 */ { MAD_F(0x07bd90f6) /* 0.483780825 */, 16 }, + /* 2377 */ { MAD_F(0x07beada7) /* 0.484052326 */, 16 }, + /* 2378 */ { MAD_F(0x07bfca61) /* 0.484323865 */, 16 }, + /* 2379 */ { MAD_F(0x07c0e726) /* 0.484595443 */, 16 }, + /* 2380 */ { MAD_F(0x07c203f5) /* 0.484867058 */, 16 }, + /* 2381 */ { MAD_F(0x07c320cf) /* 0.485138711 */, 16 }, + /* 2382 */ { MAD_F(0x07c43db2) /* 0.485410402 */, 16 }, + /* 2383 */ { MAD_F(0x07c55aa0) /* 0.485682131 */, 16 }, + + /* 2384 */ { MAD_F(0x07c67798) /* 0.485953899 */, 16 }, + /* 2385 */ { MAD_F(0x07c7949a) /* 0.486225704 */, 16 }, + /* 2386 */ { MAD_F(0x07c8b1a7) /* 0.486497547 */, 16 }, + /* 2387 */ { MAD_F(0x07c9cebd) /* 0.486769429 */, 16 }, + /* 2388 */ { MAD_F(0x07caebde) /* 0.487041348 */, 16 }, + /* 2389 */ { MAD_F(0x07cc0909) /* 0.487313305 */, 16 }, + /* 2390 */ { MAD_F(0x07cd263e) /* 0.487585300 */, 16 }, + /* 2391 */ { MAD_F(0x07ce437d) /* 0.487857333 */, 16 }, + /* 2392 */ { MAD_F(0x07cf60c7) /* 0.488129404 */, 16 }, + /* 2393 */ { MAD_F(0x07d07e1b) /* 0.488401513 */, 16 }, + /* 2394 */ { MAD_F(0x07d19b79) /* 0.488673660 */, 16 }, + /* 2395 */ { MAD_F(0x07d2b8e1) /* 0.488945845 */, 16 }, + /* 2396 */ { MAD_F(0x07d3d653) /* 0.489218067 */, 16 }, + /* 2397 */ { MAD_F(0x07d4f3cf) /* 0.489490328 */, 16 }, + /* 2398 */ { MAD_F(0x07d61156) /* 0.489762626 */, 16 }, + /* 2399 */ { MAD_F(0x07d72ee6) /* 0.490034962 */, 16 }, + + /* 2400 */ { MAD_F(0x07d84c81) /* 0.490307336 */, 16 }, + /* 2401 */ { MAD_F(0x07d96a26) /* 0.490579748 */, 16 }, + /* 2402 */ { MAD_F(0x07da87d5) /* 0.490852198 */, 16 }, + /* 2403 */ { MAD_F(0x07dba58f) /* 0.491124686 */, 16 }, + /* 2404 */ { MAD_F(0x07dcc352) /* 0.491397211 */, 16 }, + /* 2405 */ { MAD_F(0x07dde120) /* 0.491669774 */, 16 }, + /* 2406 */ { MAD_F(0x07defef7) /* 0.491942375 */, 16 }, + /* 2407 */ { MAD_F(0x07e01cd9) /* 0.492215014 */, 16 }, + /* 2408 */ { MAD_F(0x07e13ac5) /* 0.492487690 */, 16 }, + /* 2409 */ { MAD_F(0x07e258bc) /* 0.492760404 */, 16 }, + /* 2410 */ { MAD_F(0x07e376bc) /* 0.493033156 */, 16 }, + /* 2411 */ { MAD_F(0x07e494c6) /* 0.493305946 */, 16 }, + /* 2412 */ { MAD_F(0x07e5b2db) /* 0.493578773 */, 16 }, + /* 2413 */ { MAD_F(0x07e6d0f9) /* 0.493851638 */, 16 }, + /* 2414 */ { MAD_F(0x07e7ef22) /* 0.494124541 */, 16 }, + /* 2415 */ { MAD_F(0x07e90d55) /* 0.494397481 */, 16 }, + + /* 2416 */ { MAD_F(0x07ea2b92) /* 0.494670459 */, 16 }, + /* 2417 */ { MAD_F(0x07eb49d9) /* 0.494943475 */, 16 }, + /* 2418 */ { MAD_F(0x07ec682a) /* 0.495216529 */, 16 }, + /* 2419 */ { MAD_F(0x07ed8686) /* 0.495489620 */, 16 }, + /* 2420 */ { MAD_F(0x07eea4eb) /* 0.495762748 */, 16 }, + /* 2421 */ { MAD_F(0x07efc35b) /* 0.496035915 */, 16 }, + /* 2422 */ { MAD_F(0x07f0e1d4) /* 0.496309119 */, 16 }, + /* 2423 */ { MAD_F(0x07f20058) /* 0.496582360 */, 16 }, + /* 2424 */ { MAD_F(0x07f31ee6) /* 0.496855639 */, 16 }, + /* 2425 */ { MAD_F(0x07f43d7e) /* 0.497128956 */, 16 }, + /* 2426 */ { MAD_F(0x07f55c20) /* 0.497402310 */, 16 }, + /* 2427 */ { MAD_F(0x07f67acc) /* 0.497675702 */, 16 }, + /* 2428 */ { MAD_F(0x07f79982) /* 0.497949132 */, 16 }, + /* 2429 */ { MAD_F(0x07f8b842) /* 0.498222598 */, 16 }, + /* 2430 */ { MAD_F(0x07f9d70c) /* 0.498496103 */, 16 }, + /* 2431 */ { MAD_F(0x07faf5e1) /* 0.498769645 */, 16 }, + + /* 2432 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 16 }, + /* 2433 */ { MAD_F(0x07fd33a8) /* 0.499316841 */, 16 }, + /* 2434 */ { MAD_F(0x07fe529a) /* 0.499590496 */, 16 }, + /* 2435 */ { MAD_F(0x07ff7197) /* 0.499864188 */, 16 }, + /* 2436 */ { MAD_F(0x0400484f) /* 0.250068959 */, 17 }, + /* 2437 */ { MAD_F(0x0400d7d7) /* 0.250205842 */, 17 }, + /* 2438 */ { MAD_F(0x04016764) /* 0.250342744 */, 17 }, + /* 2439 */ { MAD_F(0x0401f6f7) /* 0.250479665 */, 17 }, + /* 2440 */ { MAD_F(0x0402868e) /* 0.250616605 */, 17 }, + /* 2441 */ { MAD_F(0x0403162b) /* 0.250753563 */, 17 }, + /* 2442 */ { MAD_F(0x0403a5cc) /* 0.250890540 */, 17 }, + /* 2443 */ { MAD_F(0x04043573) /* 0.251027536 */, 17 }, + /* 2444 */ { MAD_F(0x0404c51e) /* 0.251164550 */, 17 }, + /* 2445 */ { MAD_F(0x040554cf) /* 0.251301583 */, 17 }, + /* 2446 */ { MAD_F(0x0405e484) /* 0.251438635 */, 17 }, + /* 2447 */ { MAD_F(0x0406743f) /* 0.251575706 */, 17 }, + + /* 2448 */ { MAD_F(0x040703ff) /* 0.251712795 */, 17 }, + /* 2449 */ { MAD_F(0x040793c3) /* 0.251849903 */, 17 }, + /* 2450 */ { MAD_F(0x0408238d) /* 0.251987029 */, 17 }, + /* 2451 */ { MAD_F(0x0408b35b) /* 0.252124174 */, 17 }, + /* 2452 */ { MAD_F(0x0409432f) /* 0.252261338 */, 17 }, + /* 2453 */ { MAD_F(0x0409d308) /* 0.252398520 */, 17 }, + /* 2454 */ { MAD_F(0x040a62e5) /* 0.252535721 */, 17 }, + /* 2455 */ { MAD_F(0x040af2c8) /* 0.252672941 */, 17 }, + /* 2456 */ { MAD_F(0x040b82b0) /* 0.252810180 */, 17 }, + /* 2457 */ { MAD_F(0x040c129c) /* 0.252947436 */, 17 }, + /* 2458 */ { MAD_F(0x040ca28e) /* 0.253084712 */, 17 }, + /* 2459 */ { MAD_F(0x040d3284) /* 0.253222006 */, 17 }, + /* 2460 */ { MAD_F(0x040dc280) /* 0.253359319 */, 17 }, + /* 2461 */ { MAD_F(0x040e5281) /* 0.253496651 */, 17 }, + /* 2462 */ { MAD_F(0x040ee286) /* 0.253634001 */, 17 }, + /* 2463 */ { MAD_F(0x040f7291) /* 0.253771369 */, 17 }, + + /* 2464 */ { MAD_F(0x041002a1) /* 0.253908756 */, 17 }, + /* 2465 */ { MAD_F(0x041092b5) /* 0.254046162 */, 17 }, + /* 2466 */ { MAD_F(0x041122cf) /* 0.254183587 */, 17 }, + /* 2467 */ { MAD_F(0x0411b2ed) /* 0.254321030 */, 17 }, + /* 2468 */ { MAD_F(0x04124311) /* 0.254458491 */, 17 }, + /* 2469 */ { MAD_F(0x0412d339) /* 0.254595971 */, 17 }, + /* 2470 */ { MAD_F(0x04136367) /* 0.254733470 */, 17 }, + /* 2471 */ { MAD_F(0x0413f399) /* 0.254870987 */, 17 }, + /* 2472 */ { MAD_F(0x041483d1) /* 0.255008523 */, 17 }, + /* 2473 */ { MAD_F(0x0415140d) /* 0.255146077 */, 17 }, + /* 2474 */ { MAD_F(0x0415a44f) /* 0.255283650 */, 17 }, + /* 2475 */ { MAD_F(0x04163495) /* 0.255421241 */, 17 }, + /* 2476 */ { MAD_F(0x0416c4e1) /* 0.255558851 */, 17 }, + /* 2477 */ { MAD_F(0x04175531) /* 0.255696480 */, 17 }, + /* 2478 */ { MAD_F(0x0417e586) /* 0.255834127 */, 17 }, + /* 2479 */ { MAD_F(0x041875e1) /* 0.255971792 */, 17 }, + + /* 2480 */ { MAD_F(0x04190640) /* 0.256109476 */, 17 }, + /* 2481 */ { MAD_F(0x041996a4) /* 0.256247179 */, 17 }, + /* 2482 */ { MAD_F(0x041a270d) /* 0.256384900 */, 17 }, + /* 2483 */ { MAD_F(0x041ab77b) /* 0.256522639 */, 17 }, + /* 2484 */ { MAD_F(0x041b47ef) /* 0.256660397 */, 17 }, + /* 2485 */ { MAD_F(0x041bd867) /* 0.256798174 */, 17 }, + /* 2486 */ { MAD_F(0x041c68e4) /* 0.256935969 */, 17 }, + /* 2487 */ { MAD_F(0x041cf966) /* 0.257073782 */, 17 }, + /* 2488 */ { MAD_F(0x041d89ed) /* 0.257211614 */, 17 }, + /* 2489 */ { MAD_F(0x041e1a79) /* 0.257349465 */, 17 }, + /* 2490 */ { MAD_F(0x041eab0a) /* 0.257487334 */, 17 }, + /* 2491 */ { MAD_F(0x041f3b9f) /* 0.257625221 */, 17 }, + /* 2492 */ { MAD_F(0x041fcc3a) /* 0.257763127 */, 17 }, + /* 2493 */ { MAD_F(0x04205cda) /* 0.257901051 */, 17 }, + /* 2494 */ { MAD_F(0x0420ed7f) /* 0.258038994 */, 17 }, + /* 2495 */ { MAD_F(0x04217e28) /* 0.258176955 */, 17 }, + + /* 2496 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 17 }, + /* 2497 */ { MAD_F(0x04229f8a) /* 0.258452932 */, 17 }, + /* 2498 */ { MAD_F(0x04233043) /* 0.258590948 */, 17 }, + /* 2499 */ { MAD_F(0x0423c100) /* 0.258728983 */, 17 }, + /* 2500 */ { MAD_F(0x042451c3) /* 0.258867036 */, 17 }, + /* 2501 */ { MAD_F(0x0424e28a) /* 0.259005108 */, 17 }, + /* 2502 */ { MAD_F(0x04257356) /* 0.259143198 */, 17 }, + /* 2503 */ { MAD_F(0x04260428) /* 0.259281307 */, 17 }, + /* 2504 */ { MAD_F(0x042694fe) /* 0.259419433 */, 17 }, + /* 2505 */ { MAD_F(0x042725d9) /* 0.259557579 */, 17 }, + /* 2506 */ { MAD_F(0x0427b6b9) /* 0.259695742 */, 17 }, + /* 2507 */ { MAD_F(0x0428479e) /* 0.259833924 */, 17 }, + /* 2508 */ { MAD_F(0x0428d888) /* 0.259972124 */, 17 }, + /* 2509 */ { MAD_F(0x04296976) /* 0.260110343 */, 17 }, + /* 2510 */ { MAD_F(0x0429fa6a) /* 0.260248580 */, 17 }, + /* 2511 */ { MAD_F(0x042a8b63) /* 0.260386836 */, 17 }, + + /* 2512 */ { MAD_F(0x042b1c60) /* 0.260525110 */, 17 }, + /* 2513 */ { MAD_F(0x042bad63) /* 0.260663402 */, 17 }, + /* 2514 */ { MAD_F(0x042c3e6a) /* 0.260801712 */, 17 }, + /* 2515 */ { MAD_F(0x042ccf77) /* 0.260940041 */, 17 }, + /* 2516 */ { MAD_F(0x042d6088) /* 0.261078388 */, 17 }, + /* 2517 */ { MAD_F(0x042df19e) /* 0.261216754 */, 17 }, + /* 2518 */ { MAD_F(0x042e82b9) /* 0.261355137 */, 17 }, + /* 2519 */ { MAD_F(0x042f13d9) /* 0.261493540 */, 17 }, + /* 2520 */ { MAD_F(0x042fa4fe) /* 0.261631960 */, 17 }, + /* 2521 */ { MAD_F(0x04303628) /* 0.261770399 */, 17 }, + /* 2522 */ { MAD_F(0x0430c757) /* 0.261908856 */, 17 }, + /* 2523 */ { MAD_F(0x0431588b) /* 0.262047331 */, 17 }, + /* 2524 */ { MAD_F(0x0431e9c3) /* 0.262185825 */, 17 }, + /* 2525 */ { MAD_F(0x04327b01) /* 0.262324337 */, 17 }, + /* 2526 */ { MAD_F(0x04330c43) /* 0.262462867 */, 17 }, + /* 2527 */ { MAD_F(0x04339d8a) /* 0.262601416 */, 17 }, + + /* 2528 */ { MAD_F(0x04342ed7) /* 0.262739982 */, 17 }, + /* 2529 */ { MAD_F(0x0434c028) /* 0.262878568 */, 17 }, + /* 2530 */ { MAD_F(0x0435517e) /* 0.263017171 */, 17 }, + /* 2531 */ { MAD_F(0x0435e2d9) /* 0.263155792 */, 17 }, + /* 2532 */ { MAD_F(0x04367439) /* 0.263294432 */, 17 }, + /* 2533 */ { MAD_F(0x0437059e) /* 0.263433090 */, 17 }, + /* 2534 */ { MAD_F(0x04379707) /* 0.263571767 */, 17 }, + /* 2535 */ { MAD_F(0x04382876) /* 0.263710461 */, 17 }, + /* 2536 */ { MAD_F(0x0438b9e9) /* 0.263849174 */, 17 }, + /* 2537 */ { MAD_F(0x04394b61) /* 0.263987905 */, 17 }, + /* 2538 */ { MAD_F(0x0439dcdf) /* 0.264126655 */, 17 }, + /* 2539 */ { MAD_F(0x043a6e61) /* 0.264265422 */, 17 }, + /* 2540 */ { MAD_F(0x043affe8) /* 0.264404208 */, 17 }, + /* 2541 */ { MAD_F(0x043b9174) /* 0.264543012 */, 17 }, + /* 2542 */ { MAD_F(0x043c2305) /* 0.264681834 */, 17 }, + /* 2543 */ { MAD_F(0x043cb49a) /* 0.264820674 */, 17 }, + + /* 2544 */ { MAD_F(0x043d4635) /* 0.264959533 */, 17 }, + /* 2545 */ { MAD_F(0x043dd7d4) /* 0.265098410 */, 17 }, + /* 2546 */ { MAD_F(0x043e6979) /* 0.265237305 */, 17 }, + /* 2547 */ { MAD_F(0x043efb22) /* 0.265376218 */, 17 }, + /* 2548 */ { MAD_F(0x043f8cd0) /* 0.265515149 */, 17 }, + /* 2549 */ { MAD_F(0x04401e83) /* 0.265654099 */, 17 }, + /* 2550 */ { MAD_F(0x0440b03b) /* 0.265793066 */, 17 }, + /* 2551 */ { MAD_F(0x044141f7) /* 0.265932052 */, 17 }, + /* 2552 */ { MAD_F(0x0441d3b9) /* 0.266071056 */, 17 }, + /* 2553 */ { MAD_F(0x04426580) /* 0.266210078 */, 17 }, + /* 2554 */ { MAD_F(0x0442f74b) /* 0.266349119 */, 17 }, + /* 2555 */ { MAD_F(0x0443891b) /* 0.266488177 */, 17 }, + /* 2556 */ { MAD_F(0x04441af0) /* 0.266627254 */, 17 }, + /* 2557 */ { MAD_F(0x0444acca) /* 0.266766349 */, 17 }, + /* 2558 */ { MAD_F(0x04453ea9) /* 0.266905462 */, 17 }, + /* 2559 */ { MAD_F(0x0445d08d) /* 0.267044593 */, 17 }, + + /* 2560 */ { MAD_F(0x04466275) /* 0.267183742 */, 17 }, + /* 2561 */ { MAD_F(0x0446f463) /* 0.267322909 */, 17 }, + /* 2562 */ { MAD_F(0x04478655) /* 0.267462094 */, 17 }, + /* 2563 */ { MAD_F(0x0448184c) /* 0.267601298 */, 17 }, + /* 2564 */ { MAD_F(0x0448aa48) /* 0.267740519 */, 17 }, + /* 2565 */ { MAD_F(0x04493c49) /* 0.267879759 */, 17 }, + /* 2566 */ { MAD_F(0x0449ce4f) /* 0.268019017 */, 17 }, + /* 2567 */ { MAD_F(0x044a6059) /* 0.268158293 */, 17 }, + /* 2568 */ { MAD_F(0x044af269) /* 0.268297587 */, 17 }, + /* 2569 */ { MAD_F(0x044b847d) /* 0.268436899 */, 17 }, + /* 2570 */ { MAD_F(0x044c1696) /* 0.268576229 */, 17 }, + /* 2571 */ { MAD_F(0x044ca8b4) /* 0.268715577 */, 17 }, + /* 2572 */ { MAD_F(0x044d3ad7) /* 0.268854943 */, 17 }, + /* 2573 */ { MAD_F(0x044dccff) /* 0.268994328 */, 17 }, + /* 2574 */ { MAD_F(0x044e5f2b) /* 0.269133730 */, 17 }, + /* 2575 */ { MAD_F(0x044ef15d) /* 0.269273150 */, 17 }, + + /* 2576 */ { MAD_F(0x044f8393) /* 0.269412589 */, 17 }, + /* 2577 */ { MAD_F(0x045015ce) /* 0.269552045 */, 17 }, + /* 2578 */ { MAD_F(0x0450a80e) /* 0.269691520 */, 17 }, + /* 2579 */ { MAD_F(0x04513a53) /* 0.269831013 */, 17 }, + /* 2580 */ { MAD_F(0x0451cc9c) /* 0.269970523 */, 17 }, + /* 2581 */ { MAD_F(0x04525eeb) /* 0.270110052 */, 17 }, + /* 2582 */ { MAD_F(0x0452f13e) /* 0.270249599 */, 17 }, + /* 2583 */ { MAD_F(0x04538396) /* 0.270389163 */, 17 }, + /* 2584 */ { MAD_F(0x045415f3) /* 0.270528746 */, 17 }, + /* 2585 */ { MAD_F(0x0454a855) /* 0.270668347 */, 17 }, + /* 2586 */ { MAD_F(0x04553abb) /* 0.270807965 */, 17 }, + /* 2587 */ { MAD_F(0x0455cd27) /* 0.270947602 */, 17 }, + /* 2588 */ { MAD_F(0x04565f97) /* 0.271087257 */, 17 }, + /* 2589 */ { MAD_F(0x0456f20c) /* 0.271226930 */, 17 }, + /* 2590 */ { MAD_F(0x04578486) /* 0.271366620 */, 17 }, + /* 2591 */ { MAD_F(0x04581705) /* 0.271506329 */, 17 }, + + /* 2592 */ { MAD_F(0x0458a989) /* 0.271646056 */, 17 }, + /* 2593 */ { MAD_F(0x04593c11) /* 0.271785800 */, 17 }, + /* 2594 */ { MAD_F(0x0459ce9e) /* 0.271925563 */, 17 }, + /* 2595 */ { MAD_F(0x045a6130) /* 0.272065343 */, 17 }, + /* 2596 */ { MAD_F(0x045af3c7) /* 0.272205142 */, 17 }, + /* 2597 */ { MAD_F(0x045b8663) /* 0.272344958 */, 17 }, + /* 2598 */ { MAD_F(0x045c1903) /* 0.272484793 */, 17 }, + /* 2599 */ { MAD_F(0x045caba9) /* 0.272624645 */, 17 }, + /* 2600 */ { MAD_F(0x045d3e53) /* 0.272764515 */, 17 }, + /* 2601 */ { MAD_F(0x045dd102) /* 0.272904403 */, 17 }, + /* 2602 */ { MAD_F(0x045e63b6) /* 0.273044310 */, 17 }, + /* 2603 */ { MAD_F(0x045ef66e) /* 0.273184234 */, 17 }, + /* 2604 */ { MAD_F(0x045f892b) /* 0.273324176 */, 17 }, + /* 2605 */ { MAD_F(0x04601bee) /* 0.273464136 */, 17 }, + /* 2606 */ { MAD_F(0x0460aeb5) /* 0.273604113 */, 17 }, + /* 2607 */ { MAD_F(0x04614180) /* 0.273744109 */, 17 }, + + /* 2608 */ { MAD_F(0x0461d451) /* 0.273884123 */, 17 }, + /* 2609 */ { MAD_F(0x04626727) /* 0.274024154 */, 17 }, + /* 2610 */ { MAD_F(0x0462fa01) /* 0.274164204 */, 17 }, + /* 2611 */ { MAD_F(0x04638ce0) /* 0.274304271 */, 17 }, + /* 2612 */ { MAD_F(0x04641fc4) /* 0.274444356 */, 17 }, + /* 2613 */ { MAD_F(0x0464b2ac) /* 0.274584459 */, 17 }, + /* 2614 */ { MAD_F(0x0465459a) /* 0.274724580 */, 17 }, + /* 2615 */ { MAD_F(0x0465d88c) /* 0.274864719 */, 17 }, + /* 2616 */ { MAD_F(0x04666b83) /* 0.275004875 */, 17 }, + /* 2617 */ { MAD_F(0x0466fe7f) /* 0.275145050 */, 17 }, + /* 2618 */ { MAD_F(0x0467917f) /* 0.275285242 */, 17 }, + /* 2619 */ { MAD_F(0x04682485) /* 0.275425452 */, 17 }, + /* 2620 */ { MAD_F(0x0468b78f) /* 0.275565681 */, 17 }, + /* 2621 */ { MAD_F(0x04694a9e) /* 0.275705926 */, 17 }, + /* 2622 */ { MAD_F(0x0469ddb2) /* 0.275846190 */, 17 }, + /* 2623 */ { MAD_F(0x046a70ca) /* 0.275986472 */, 17 }, + + /* 2624 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 17 }, + /* 2625 */ { MAD_F(0x046b970a) /* 0.276267088 */, 17 }, + /* 2626 */ { MAD_F(0x046c2a31) /* 0.276407423 */, 17 }, + /* 2627 */ { MAD_F(0x046cbd5c) /* 0.276547776 */, 17 }, + /* 2628 */ { MAD_F(0x046d508d) /* 0.276688147 */, 17 }, + /* 2629 */ { MAD_F(0x046de3c2) /* 0.276828535 */, 17 }, + /* 2630 */ { MAD_F(0x046e76fc) /* 0.276968942 */, 17 }, + /* 2631 */ { MAD_F(0x046f0a3b) /* 0.277109366 */, 17 }, + /* 2632 */ { MAD_F(0x046f9d7e) /* 0.277249808 */, 17 }, + /* 2633 */ { MAD_F(0x047030c7) /* 0.277390267 */, 17 }, + /* 2634 */ { MAD_F(0x0470c414) /* 0.277530745 */, 17 }, + /* 2635 */ { MAD_F(0x04715766) /* 0.277671240 */, 17 }, + /* 2636 */ { MAD_F(0x0471eabc) /* 0.277811753 */, 17 }, + /* 2637 */ { MAD_F(0x04727e18) /* 0.277952284 */, 17 }, + /* 2638 */ { MAD_F(0x04731178) /* 0.278092832 */, 17 }, + /* 2639 */ { MAD_F(0x0473a4dd) /* 0.278233399 */, 17 }, + + /* 2640 */ { MAD_F(0x04743847) /* 0.278373983 */, 17 }, + /* 2641 */ { MAD_F(0x0474cbb5) /* 0.278514584 */, 17 }, + /* 2642 */ { MAD_F(0x04755f29) /* 0.278655204 */, 17 }, + /* 2643 */ { MAD_F(0x0475f2a1) /* 0.278795841 */, 17 }, + /* 2644 */ { MAD_F(0x0476861d) /* 0.278936496 */, 17 }, + /* 2645 */ { MAD_F(0x0477199f) /* 0.279077169 */, 17 }, + /* 2646 */ { MAD_F(0x0477ad25) /* 0.279217860 */, 17 }, + /* 2647 */ { MAD_F(0x047840b0) /* 0.279358568 */, 17 }, + /* 2648 */ { MAD_F(0x0478d440) /* 0.279499294 */, 17 }, + /* 2649 */ { MAD_F(0x047967d5) /* 0.279640037 */, 17 }, + /* 2650 */ { MAD_F(0x0479fb6e) /* 0.279780799 */, 17 }, + /* 2651 */ { MAD_F(0x047a8f0c) /* 0.279921578 */, 17 }, + /* 2652 */ { MAD_F(0x047b22af) /* 0.280062375 */, 17 }, + /* 2653 */ { MAD_F(0x047bb657) /* 0.280203189 */, 17 }, + /* 2654 */ { MAD_F(0x047c4a03) /* 0.280344021 */, 17 }, + /* 2655 */ { MAD_F(0x047cddb4) /* 0.280484871 */, 17 }, + + /* 2656 */ { MAD_F(0x047d716a) /* 0.280625739 */, 17 }, + /* 2657 */ { MAD_F(0x047e0524) /* 0.280766624 */, 17 }, + /* 2658 */ { MAD_F(0x047e98e4) /* 0.280907527 */, 17 }, + /* 2659 */ { MAD_F(0x047f2ca8) /* 0.281048447 */, 17 }, + /* 2660 */ { MAD_F(0x047fc071) /* 0.281189385 */, 17 }, + /* 2661 */ { MAD_F(0x0480543e) /* 0.281330341 */, 17 }, + /* 2662 */ { MAD_F(0x0480e811) /* 0.281471315 */, 17 }, + /* 2663 */ { MAD_F(0x04817be8) /* 0.281612306 */, 17 }, + /* 2664 */ { MAD_F(0x04820fc3) /* 0.281753315 */, 17 }, + /* 2665 */ { MAD_F(0x0482a3a4) /* 0.281894341 */, 17 }, + /* 2666 */ { MAD_F(0x04833789) /* 0.282035386 */, 17 }, + /* 2667 */ { MAD_F(0x0483cb73) /* 0.282176447 */, 17 }, + /* 2668 */ { MAD_F(0x04845f62) /* 0.282317527 */, 17 }, + /* 2669 */ { MAD_F(0x0484f355) /* 0.282458624 */, 17 }, + /* 2670 */ { MAD_F(0x0485874d) /* 0.282599738 */, 17 }, + /* 2671 */ { MAD_F(0x04861b4a) /* 0.282740871 */, 17 }, + + /* 2672 */ { MAD_F(0x0486af4c) /* 0.282882021 */, 17 }, + /* 2673 */ { MAD_F(0x04874352) /* 0.283023188 */, 17 }, + /* 2674 */ { MAD_F(0x0487d75d) /* 0.283164373 */, 17 }, + /* 2675 */ { MAD_F(0x04886b6d) /* 0.283305576 */, 17 }, + /* 2676 */ { MAD_F(0x0488ff82) /* 0.283446796 */, 17 }, + /* 2677 */ { MAD_F(0x0489939b) /* 0.283588034 */, 17 }, + /* 2678 */ { MAD_F(0x048a27b9) /* 0.283729290 */, 17 }, + /* 2679 */ { MAD_F(0x048abbdc) /* 0.283870563 */, 17 }, + /* 2680 */ { MAD_F(0x048b5003) /* 0.284011853 */, 17 }, + /* 2681 */ { MAD_F(0x048be42f) /* 0.284153161 */, 17 }, + /* 2682 */ { MAD_F(0x048c7860) /* 0.284294487 */, 17 }, + /* 2683 */ { MAD_F(0x048d0c96) /* 0.284435831 */, 17 }, + /* 2684 */ { MAD_F(0x048da0d0) /* 0.284577192 */, 17 }, + /* 2685 */ { MAD_F(0x048e350f) /* 0.284718570 */, 17 }, + /* 2686 */ { MAD_F(0x048ec953) /* 0.284859966 */, 17 }, + /* 2687 */ { MAD_F(0x048f5d9b) /* 0.285001380 */, 17 }, + + /* 2688 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 17 }, + /* 2689 */ { MAD_F(0x0490863a) /* 0.285284259 */, 17 }, + /* 2690 */ { MAD_F(0x04911a91) /* 0.285425726 */, 17 }, + /* 2691 */ { MAD_F(0x0491aeec) /* 0.285567209 */, 17 }, + /* 2692 */ { MAD_F(0x0492434c) /* 0.285708711 */, 17 }, + /* 2693 */ { MAD_F(0x0492d7b0) /* 0.285850229 */, 17 }, + /* 2694 */ { MAD_F(0x04936c1a) /* 0.285991766 */, 17 }, + /* 2695 */ { MAD_F(0x04940088) /* 0.286133319 */, 17 }, + /* 2696 */ { MAD_F(0x049494fb) /* 0.286274891 */, 17 }, + /* 2697 */ { MAD_F(0x04952972) /* 0.286416480 */, 17 }, + /* 2698 */ { MAD_F(0x0495bdee) /* 0.286558086 */, 17 }, + /* 2699 */ { MAD_F(0x0496526f) /* 0.286699710 */, 17 }, + /* 2700 */ { MAD_F(0x0496e6f5) /* 0.286841351 */, 17 }, + /* 2701 */ { MAD_F(0x04977b7f) /* 0.286983010 */, 17 }, + /* 2702 */ { MAD_F(0x0498100e) /* 0.287124686 */, 17 }, + /* 2703 */ { MAD_F(0x0498a4a1) /* 0.287266380 */, 17 }, + + /* 2704 */ { MAD_F(0x0499393a) /* 0.287408091 */, 17 }, + /* 2705 */ { MAD_F(0x0499cdd7) /* 0.287549820 */, 17 }, + /* 2706 */ { MAD_F(0x049a6278) /* 0.287691566 */, 17 }, + /* 2707 */ { MAD_F(0x049af71f) /* 0.287833330 */, 17 }, + /* 2708 */ { MAD_F(0x049b8bca) /* 0.287975111 */, 17 }, + /* 2709 */ { MAD_F(0x049c207a) /* 0.288116909 */, 17 }, + /* 2710 */ { MAD_F(0x049cb52e) /* 0.288258725 */, 17 }, + /* 2711 */ { MAD_F(0x049d49e7) /* 0.288400559 */, 17 }, + /* 2712 */ { MAD_F(0x049ddea5) /* 0.288542409 */, 17 }, + /* 2713 */ { MAD_F(0x049e7367) /* 0.288684278 */, 17 }, + /* 2714 */ { MAD_F(0x049f082f) /* 0.288826163 */, 17 }, + /* 2715 */ { MAD_F(0x049f9cfa) /* 0.288968067 */, 17 }, + /* 2716 */ { MAD_F(0x04a031cb) /* 0.289109987 */, 17 }, + /* 2717 */ { MAD_F(0x04a0c6a0) /* 0.289251925 */, 17 }, + /* 2718 */ { MAD_F(0x04a15b7a) /* 0.289393881 */, 17 }, + /* 2719 */ { MAD_F(0x04a1f059) /* 0.289535854 */, 17 }, + + /* 2720 */ { MAD_F(0x04a2853c) /* 0.289677844 */, 17 }, + /* 2721 */ { MAD_F(0x04a31a24) /* 0.289819851 */, 17 }, + /* 2722 */ { MAD_F(0x04a3af10) /* 0.289961876 */, 17 }, + /* 2723 */ { MAD_F(0x04a44401) /* 0.290103919 */, 17 }, + /* 2724 */ { MAD_F(0x04a4d8f7) /* 0.290245979 */, 17 }, + /* 2725 */ { MAD_F(0x04a56df2) /* 0.290388056 */, 17 }, + /* 2726 */ { MAD_F(0x04a602f1) /* 0.290530150 */, 17 }, + /* 2727 */ { MAD_F(0x04a697f5) /* 0.290672262 */, 17 }, + /* 2728 */ { MAD_F(0x04a72cfe) /* 0.290814392 */, 17 }, + /* 2729 */ { MAD_F(0x04a7c20b) /* 0.290956538 */, 17 }, + /* 2730 */ { MAD_F(0x04a8571d) /* 0.291098703 */, 17 }, + /* 2731 */ { MAD_F(0x04a8ec33) /* 0.291240884 */, 17 }, + /* 2732 */ { MAD_F(0x04a9814e) /* 0.291383083 */, 17 }, + /* 2733 */ { MAD_F(0x04aa166e) /* 0.291525299 */, 17 }, + /* 2734 */ { MAD_F(0x04aaab93) /* 0.291667532 */, 17 }, + /* 2735 */ { MAD_F(0x04ab40bc) /* 0.291809783 */, 17 }, + + /* 2736 */ { MAD_F(0x04abd5ea) /* 0.291952051 */, 17 }, + /* 2737 */ { MAD_F(0x04ac6b1c) /* 0.292094337 */, 17 }, + /* 2738 */ { MAD_F(0x04ad0053) /* 0.292236640 */, 17 }, + /* 2739 */ { MAD_F(0x04ad958f) /* 0.292378960 */, 17 }, + /* 2740 */ { MAD_F(0x04ae2ad0) /* 0.292521297 */, 17 }, + /* 2741 */ { MAD_F(0x04aec015) /* 0.292663652 */, 17 }, + /* 2742 */ { MAD_F(0x04af555e) /* 0.292806024 */, 17 }, + /* 2743 */ { MAD_F(0x04afeaad) /* 0.292948414 */, 17 }, + /* 2744 */ { MAD_F(0x04b08000) /* 0.293090820 */, 17 }, + /* 2745 */ { MAD_F(0x04b11557) /* 0.293233244 */, 17 }, + /* 2746 */ { MAD_F(0x04b1aab4) /* 0.293375686 */, 17 }, + /* 2747 */ { MAD_F(0x04b24015) /* 0.293518144 */, 17 }, + /* 2748 */ { MAD_F(0x04b2d57a) /* 0.293660620 */, 17 }, + /* 2749 */ { MAD_F(0x04b36ae4) /* 0.293803113 */, 17 }, + /* 2750 */ { MAD_F(0x04b40053) /* 0.293945624 */, 17 }, + /* 2751 */ { MAD_F(0x04b495c7) /* 0.294088151 */, 17 }, + + /* 2752 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 17 }, + /* 2753 */ { MAD_F(0x04b5c0bc) /* 0.294373259 */, 17 }, + /* 2754 */ { MAD_F(0x04b6563d) /* 0.294515838 */, 17 }, + /* 2755 */ { MAD_F(0x04b6ebc3) /* 0.294658435 */, 17 }, + /* 2756 */ { MAD_F(0x04b7814e) /* 0.294801049 */, 17 }, + /* 2757 */ { MAD_F(0x04b816dd) /* 0.294943680 */, 17 }, + /* 2758 */ { MAD_F(0x04b8ac71) /* 0.295086329 */, 17 }, + /* 2759 */ { MAD_F(0x04b9420a) /* 0.295228995 */, 17 }, + /* 2760 */ { MAD_F(0x04b9d7a7) /* 0.295371678 */, 17 }, + /* 2761 */ { MAD_F(0x04ba6d49) /* 0.295514378 */, 17 }, + /* 2762 */ { MAD_F(0x04bb02ef) /* 0.295657095 */, 17 }, + /* 2763 */ { MAD_F(0x04bb989a) /* 0.295799830 */, 17 }, + /* 2764 */ { MAD_F(0x04bc2e4a) /* 0.295942582 */, 17 }, + /* 2765 */ { MAD_F(0x04bcc3fe) /* 0.296085351 */, 17 }, + /* 2766 */ { MAD_F(0x04bd59b7) /* 0.296228138 */, 17 }, + /* 2767 */ { MAD_F(0x04bdef74) /* 0.296370941 */, 17 }, + + /* 2768 */ { MAD_F(0x04be8537) /* 0.296513762 */, 17 }, + /* 2769 */ { MAD_F(0x04bf1afd) /* 0.296656600 */, 17 }, + /* 2770 */ { MAD_F(0x04bfb0c9) /* 0.296799455 */, 17 }, + /* 2771 */ { MAD_F(0x04c04699) /* 0.296942327 */, 17 }, + /* 2772 */ { MAD_F(0x04c0dc6d) /* 0.297085217 */, 17 }, + /* 2773 */ { MAD_F(0x04c17247) /* 0.297228124 */, 17 }, + /* 2774 */ { MAD_F(0x04c20824) /* 0.297371048 */, 17 }, + /* 2775 */ { MAD_F(0x04c29e07) /* 0.297513989 */, 17 }, + /* 2776 */ { MAD_F(0x04c333ee) /* 0.297656947 */, 17 }, + /* 2777 */ { MAD_F(0x04c3c9da) /* 0.297799922 */, 17 }, + /* 2778 */ { MAD_F(0x04c45fca) /* 0.297942915 */, 17 }, + /* 2779 */ { MAD_F(0x04c4f5bf) /* 0.298085925 */, 17 }, + /* 2780 */ { MAD_F(0x04c58bb8) /* 0.298228951 */, 17 }, + /* 2781 */ { MAD_F(0x04c621b6) /* 0.298371996 */, 17 }, + /* 2782 */ { MAD_F(0x04c6b7b9) /* 0.298515057 */, 17 }, + /* 2783 */ { MAD_F(0x04c74dc0) /* 0.298658135 */, 17 }, + + /* 2784 */ { MAD_F(0x04c7e3cc) /* 0.298801231 */, 17 }, + /* 2785 */ { MAD_F(0x04c879dd) /* 0.298944343 */, 17 }, + /* 2786 */ { MAD_F(0x04c90ff2) /* 0.299087473 */, 17 }, + /* 2787 */ { MAD_F(0x04c9a60c) /* 0.299230620 */, 17 }, + /* 2788 */ { MAD_F(0x04ca3c2a) /* 0.299373784 */, 17 }, + /* 2789 */ { MAD_F(0x04cad24d) /* 0.299516965 */, 17 }, + /* 2790 */ { MAD_F(0x04cb6874) /* 0.299660163 */, 17 }, + /* 2791 */ { MAD_F(0x04cbfea0) /* 0.299803378 */, 17 }, + /* 2792 */ { MAD_F(0x04cc94d1) /* 0.299946611 */, 17 }, + /* 2793 */ { MAD_F(0x04cd2b06) /* 0.300089860 */, 17 }, + /* 2794 */ { MAD_F(0x04cdc140) /* 0.300233127 */, 17 }, + /* 2795 */ { MAD_F(0x04ce577f) /* 0.300376411 */, 17 }, + /* 2796 */ { MAD_F(0x04ceedc2) /* 0.300519711 */, 17 }, + /* 2797 */ { MAD_F(0x04cf8409) /* 0.300663029 */, 17 }, + /* 2798 */ { MAD_F(0x04d01a55) /* 0.300806364 */, 17 }, + /* 2799 */ { MAD_F(0x04d0b0a6) /* 0.300949716 */, 17 }, + + /* 2800 */ { MAD_F(0x04d146fb) /* 0.301093085 */, 17 }, + /* 2801 */ { MAD_F(0x04d1dd55) /* 0.301236472 */, 17 }, + /* 2802 */ { MAD_F(0x04d273b4) /* 0.301379875 */, 17 }, + /* 2803 */ { MAD_F(0x04d30a17) /* 0.301523295 */, 17 }, + /* 2804 */ { MAD_F(0x04d3a07f) /* 0.301666733 */, 17 }, + /* 2805 */ { MAD_F(0x04d436eb) /* 0.301810187 */, 17 }, + /* 2806 */ { MAD_F(0x04d4cd5c) /* 0.301953659 */, 17 }, + /* 2807 */ { MAD_F(0x04d563d1) /* 0.302097147 */, 17 }, + /* 2808 */ { MAD_F(0x04d5fa4b) /* 0.302240653 */, 17 }, + /* 2809 */ { MAD_F(0x04d690ca) /* 0.302384175 */, 17 }, + /* 2810 */ { MAD_F(0x04d7274d) /* 0.302527715 */, 17 }, + /* 2811 */ { MAD_F(0x04d7bdd5) /* 0.302671271 */, 17 }, + /* 2812 */ { MAD_F(0x04d85461) /* 0.302814845 */, 17 }, + /* 2813 */ { MAD_F(0x04d8eaf2) /* 0.302958436 */, 17 }, + /* 2814 */ { MAD_F(0x04d98187) /* 0.303102044 */, 17 }, + /* 2815 */ { MAD_F(0x04da1821) /* 0.303245668 */, 17 }, + + /* 2816 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 17 }, + /* 2817 */ { MAD_F(0x04db4563) /* 0.303532969 */, 17 }, + /* 2818 */ { MAD_F(0x04dbdc0a) /* 0.303676645 */, 17 }, + /* 2819 */ { MAD_F(0x04dc72b7) /* 0.303820337 */, 17 }, + /* 2820 */ { MAD_F(0x04dd0967) /* 0.303964047 */, 17 }, + /* 2821 */ { MAD_F(0x04dda01d) /* 0.304107774 */, 17 }, + /* 2822 */ { MAD_F(0x04de36d7) /* 0.304251517 */, 17 }, + /* 2823 */ { MAD_F(0x04decd95) /* 0.304395278 */, 17 }, + /* 2824 */ { MAD_F(0x04df6458) /* 0.304539056 */, 17 }, + /* 2825 */ { MAD_F(0x04dffb20) /* 0.304682850 */, 17 }, + /* 2826 */ { MAD_F(0x04e091ec) /* 0.304826662 */, 17 }, + /* 2827 */ { MAD_F(0x04e128bc) /* 0.304970491 */, 17 }, + /* 2828 */ { MAD_F(0x04e1bf92) /* 0.305114336 */, 17 }, + /* 2829 */ { MAD_F(0x04e2566b) /* 0.305258199 */, 17 }, + /* 2830 */ { MAD_F(0x04e2ed4a) /* 0.305402078 */, 17 }, + /* 2831 */ { MAD_F(0x04e3842d) /* 0.305545974 */, 17 }, + + /* 2832 */ { MAD_F(0x04e41b14) /* 0.305689888 */, 17 }, + /* 2833 */ { MAD_F(0x04e4b200) /* 0.305833818 */, 17 }, + /* 2834 */ { MAD_F(0x04e548f1) /* 0.305977765 */, 17 }, + /* 2835 */ { MAD_F(0x04e5dfe6) /* 0.306121729 */, 17 }, + /* 2836 */ { MAD_F(0x04e676df) /* 0.306265710 */, 17 }, + /* 2837 */ { MAD_F(0x04e70dde) /* 0.306409708 */, 17 }, + /* 2838 */ { MAD_F(0x04e7a4e0) /* 0.306553723 */, 17 }, + /* 2839 */ { MAD_F(0x04e83be7) /* 0.306697755 */, 17 }, + /* 2840 */ { MAD_F(0x04e8d2f3) /* 0.306841804 */, 17 }, + /* 2841 */ { MAD_F(0x04e96a04) /* 0.306985869 */, 17 }, + /* 2842 */ { MAD_F(0x04ea0118) /* 0.307129952 */, 17 }, + /* 2843 */ { MAD_F(0x04ea9832) /* 0.307274051 */, 17 }, + /* 2844 */ { MAD_F(0x04eb2f50) /* 0.307418168 */, 17 }, + /* 2845 */ { MAD_F(0x04ebc672) /* 0.307562301 */, 17 }, + /* 2846 */ { MAD_F(0x04ec5d99) /* 0.307706451 */, 17 }, + /* 2847 */ { MAD_F(0x04ecf4c5) /* 0.307850618 */, 17 }, + + /* 2848 */ { MAD_F(0x04ed8bf5) /* 0.307994802 */, 17 }, + /* 2849 */ { MAD_F(0x04ee2329) /* 0.308139003 */, 17 }, + /* 2850 */ { MAD_F(0x04eeba63) /* 0.308283220 */, 17 }, + /* 2851 */ { MAD_F(0x04ef51a0) /* 0.308427455 */, 17 }, + /* 2852 */ { MAD_F(0x04efe8e2) /* 0.308571706 */, 17 }, + /* 2853 */ { MAD_F(0x04f08029) /* 0.308715974 */, 17 }, + /* 2854 */ { MAD_F(0x04f11774) /* 0.308860260 */, 17 }, + /* 2855 */ { MAD_F(0x04f1aec4) /* 0.309004561 */, 17 }, + /* 2856 */ { MAD_F(0x04f24618) /* 0.309148880 */, 17 }, + /* 2857 */ { MAD_F(0x04f2dd71) /* 0.309293216 */, 17 }, + /* 2858 */ { MAD_F(0x04f374cf) /* 0.309437568 */, 17 }, + /* 2859 */ { MAD_F(0x04f40c30) /* 0.309581938 */, 17 }, + /* 2860 */ { MAD_F(0x04f4a397) /* 0.309726324 */, 17 }, + /* 2861 */ { MAD_F(0x04f53b02) /* 0.309870727 */, 17 }, + /* 2862 */ { MAD_F(0x04f5d271) /* 0.310015147 */, 17 }, + /* 2863 */ { MAD_F(0x04f669e5) /* 0.310159583 */, 17 }, + + /* 2864 */ { MAD_F(0x04f7015d) /* 0.310304037 */, 17 }, + /* 2865 */ { MAD_F(0x04f798da) /* 0.310448507 */, 17 }, + /* 2866 */ { MAD_F(0x04f8305c) /* 0.310592994 */, 17 }, + /* 2867 */ { MAD_F(0x04f8c7e2) /* 0.310737498 */, 17 }, + /* 2868 */ { MAD_F(0x04f95f6c) /* 0.310882018 */, 17 }, + /* 2869 */ { MAD_F(0x04f9f6fb) /* 0.311026556 */, 17 }, + /* 2870 */ { MAD_F(0x04fa8e8f) /* 0.311171110 */, 17 }, + /* 2871 */ { MAD_F(0x04fb2627) /* 0.311315681 */, 17 }, + /* 2872 */ { MAD_F(0x04fbbdc3) /* 0.311460269 */, 17 }, + /* 2873 */ { MAD_F(0x04fc5564) /* 0.311604874 */, 17 }, + /* 2874 */ { MAD_F(0x04fced0a) /* 0.311749495 */, 17 }, + /* 2875 */ { MAD_F(0x04fd84b4) /* 0.311894133 */, 17 }, + /* 2876 */ { MAD_F(0x04fe1c62) /* 0.312038788 */, 17 }, + /* 2877 */ { MAD_F(0x04feb415) /* 0.312183460 */, 17 }, + /* 2878 */ { MAD_F(0x04ff4bcd) /* 0.312328148 */, 17 }, + /* 2879 */ { MAD_F(0x04ffe389) /* 0.312472854 */, 17 }, + + /* 2880 */ { MAD_F(0x05007b49) /* 0.312617576 */, 17 }, + /* 2881 */ { MAD_F(0x0501130e) /* 0.312762314 */, 17 }, + /* 2882 */ { MAD_F(0x0501aad8) /* 0.312907070 */, 17 }, + /* 2883 */ { MAD_F(0x050242a6) /* 0.313051842 */, 17 }, + /* 2884 */ { MAD_F(0x0502da78) /* 0.313196631 */, 17 }, + /* 2885 */ { MAD_F(0x0503724f) /* 0.313341437 */, 17 }, + /* 2886 */ { MAD_F(0x05040a2b) /* 0.313486259 */, 17 }, + /* 2887 */ { MAD_F(0x0504a20b) /* 0.313631098 */, 17 }, + /* 2888 */ { MAD_F(0x050539ef) /* 0.313775954 */, 17 }, + /* 2889 */ { MAD_F(0x0505d1d8) /* 0.313920827 */, 17 }, + /* 2890 */ { MAD_F(0x050669c5) /* 0.314065716 */, 17 }, + /* 2891 */ { MAD_F(0x050701b7) /* 0.314210622 */, 17 }, + /* 2892 */ { MAD_F(0x050799ae) /* 0.314355545 */, 17 }, + /* 2893 */ { MAD_F(0x050831a9) /* 0.314500484 */, 17 }, + /* 2894 */ { MAD_F(0x0508c9a8) /* 0.314645440 */, 17 }, + /* 2895 */ { MAD_F(0x050961ac) /* 0.314790413 */, 17 }, + + /* 2896 */ { MAD_F(0x0509f9b4) /* 0.314935403 */, 17 }, + /* 2897 */ { MAD_F(0x050a91c1) /* 0.315080409 */, 17 }, + /* 2898 */ { MAD_F(0x050b29d2) /* 0.315225432 */, 17 }, + /* 2899 */ { MAD_F(0x050bc1e8) /* 0.315370472 */, 17 }, + /* 2900 */ { MAD_F(0x050c5a02) /* 0.315515528 */, 17 }, + /* 2901 */ { MAD_F(0x050cf221) /* 0.315660601 */, 17 }, + /* 2902 */ { MAD_F(0x050d8a44) /* 0.315805690 */, 17 }, + /* 2903 */ { MAD_F(0x050e226c) /* 0.315950797 */, 17 }, + /* 2904 */ { MAD_F(0x050eba98) /* 0.316095920 */, 17 }, + /* 2905 */ { MAD_F(0x050f52c9) /* 0.316241059 */, 17 }, + /* 2906 */ { MAD_F(0x050feafe) /* 0.316386216 */, 17 }, + /* 2907 */ { MAD_F(0x05108337) /* 0.316531388 */, 17 }, + /* 2908 */ { MAD_F(0x05111b75) /* 0.316676578 */, 17 }, + /* 2909 */ { MAD_F(0x0511b3b8) /* 0.316821784 */, 17 }, + /* 2910 */ { MAD_F(0x05124bff) /* 0.316967007 */, 17 }, + /* 2911 */ { MAD_F(0x0512e44a) /* 0.317112247 */, 17 }, + + /* 2912 */ { MAD_F(0x05137c9a) /* 0.317257503 */, 17 }, + /* 2913 */ { MAD_F(0x051414ee) /* 0.317402775 */, 17 }, + /* 2914 */ { MAD_F(0x0514ad47) /* 0.317548065 */, 17 }, + /* 2915 */ { MAD_F(0x051545a5) /* 0.317693371 */, 17 }, + /* 2916 */ { MAD_F(0x0515de06) /* 0.317838693 */, 17 }, + /* 2917 */ { MAD_F(0x0516766d) /* 0.317984033 */, 17 }, + /* 2918 */ { MAD_F(0x05170ed7) /* 0.318129388 */, 17 }, + /* 2919 */ { MAD_F(0x0517a746) /* 0.318274761 */, 17 }, + /* 2920 */ { MAD_F(0x05183fba) /* 0.318420150 */, 17 }, + /* 2921 */ { MAD_F(0x0518d832) /* 0.318565555 */, 17 }, + /* 2922 */ { MAD_F(0x051970ae) /* 0.318710978 */, 17 }, + /* 2923 */ { MAD_F(0x051a092f) /* 0.318856416 */, 17 }, + /* 2924 */ { MAD_F(0x051aa1b5) /* 0.319001872 */, 17 }, + /* 2925 */ { MAD_F(0x051b3a3f) /* 0.319147344 */, 17 }, + /* 2926 */ { MAD_F(0x051bd2cd) /* 0.319292832 */, 17 }, + /* 2927 */ { MAD_F(0x051c6b60) /* 0.319438338 */, 17 }, + + /* 2928 */ { MAD_F(0x051d03f7) /* 0.319583859 */, 17 }, + /* 2929 */ { MAD_F(0x051d9c92) /* 0.319729398 */, 17 }, + /* 2930 */ { MAD_F(0x051e3532) /* 0.319874952 */, 17 }, + /* 2931 */ { MAD_F(0x051ecdd7) /* 0.320020524 */, 17 }, + /* 2932 */ { MAD_F(0x051f6680) /* 0.320166112 */, 17 }, + /* 2933 */ { MAD_F(0x051fff2d) /* 0.320311716 */, 17 }, + /* 2934 */ { MAD_F(0x052097df) /* 0.320457337 */, 17 }, + /* 2935 */ { MAD_F(0x05213095) /* 0.320602975 */, 17 }, + /* 2936 */ { MAD_F(0x0521c950) /* 0.320748629 */, 17 }, + /* 2937 */ { MAD_F(0x0522620f) /* 0.320894300 */, 17 }, + /* 2938 */ { MAD_F(0x0522fad3) /* 0.321039987 */, 17 }, + /* 2939 */ { MAD_F(0x0523939b) /* 0.321185691 */, 17 }, + /* 2940 */ { MAD_F(0x05242c68) /* 0.321331411 */, 17 }, + /* 2941 */ { MAD_F(0x0524c538) /* 0.321477148 */, 17 }, + /* 2942 */ { MAD_F(0x05255e0e) /* 0.321622901 */, 17 }, + /* 2943 */ { MAD_F(0x0525f6e8) /* 0.321768671 */, 17 }, + + /* 2944 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 17 }, + /* 2945 */ { MAD_F(0x052728a9) /* 0.322060260 */, 17 }, + /* 2946 */ { MAD_F(0x0527c190) /* 0.322206079 */, 17 }, + /* 2947 */ { MAD_F(0x05285a7b) /* 0.322351915 */, 17 }, + /* 2948 */ { MAD_F(0x0528f36b) /* 0.322497768 */, 17 }, + /* 2949 */ { MAD_F(0x05298c5f) /* 0.322643636 */, 17 }, + /* 2950 */ { MAD_F(0x052a2558) /* 0.322789522 */, 17 }, + /* 2951 */ { MAD_F(0x052abe55) /* 0.322935424 */, 17 }, + /* 2952 */ { MAD_F(0x052b5757) /* 0.323081342 */, 17 }, + /* 2953 */ { MAD_F(0x052bf05d) /* 0.323227277 */, 17 }, + /* 2954 */ { MAD_F(0x052c8968) /* 0.323373228 */, 17 }, + /* 2955 */ { MAD_F(0x052d2277) /* 0.323519196 */, 17 }, + /* 2956 */ { MAD_F(0x052dbb8a) /* 0.323665180 */, 17 }, + /* 2957 */ { MAD_F(0x052e54a2) /* 0.323811180 */, 17 }, + /* 2958 */ { MAD_F(0x052eedbe) /* 0.323957197 */, 17 }, + /* 2959 */ { MAD_F(0x052f86de) /* 0.324103231 */, 17 }, + + /* 2960 */ { MAD_F(0x05302003) /* 0.324249281 */, 17 }, + /* 2961 */ { MAD_F(0x0530b92d) /* 0.324395347 */, 17 }, + /* 2962 */ { MAD_F(0x0531525b) /* 0.324541430 */, 17 }, + /* 2963 */ { MAD_F(0x0531eb8d) /* 0.324687530 */, 17 }, + /* 2964 */ { MAD_F(0x053284c4) /* 0.324833646 */, 17 }, + /* 2965 */ { MAD_F(0x05331dff) /* 0.324979778 */, 17 }, + /* 2966 */ { MAD_F(0x0533b73e) /* 0.325125926 */, 17 }, + /* 2967 */ { MAD_F(0x05345082) /* 0.325272091 */, 17 }, + /* 2968 */ { MAD_F(0x0534e9ca) /* 0.325418273 */, 17 }, + /* 2969 */ { MAD_F(0x05358317) /* 0.325564471 */, 17 }, + /* 2970 */ { MAD_F(0x05361c68) /* 0.325710685 */, 17 }, + /* 2971 */ { MAD_F(0x0536b5be) /* 0.325856916 */, 17 }, + /* 2972 */ { MAD_F(0x05374f17) /* 0.326003163 */, 17 }, + /* 2973 */ { MAD_F(0x0537e876) /* 0.326149427 */, 17 }, + /* 2974 */ { MAD_F(0x053881d9) /* 0.326295707 */, 17 }, + /* 2975 */ { MAD_F(0x05391b40) /* 0.326442003 */, 17 }, + + /* 2976 */ { MAD_F(0x0539b4ab) /* 0.326588316 */, 17 }, + /* 2977 */ { MAD_F(0x053a4e1b) /* 0.326734645 */, 17 }, + /* 2978 */ { MAD_F(0x053ae78f) /* 0.326880990 */, 17 }, + /* 2979 */ { MAD_F(0x053b8108) /* 0.327027352 */, 17 }, + /* 2980 */ { MAD_F(0x053c1a85) /* 0.327173730 */, 17 }, + /* 2981 */ { MAD_F(0x053cb407) /* 0.327320125 */, 17 }, + /* 2982 */ { MAD_F(0x053d4d8d) /* 0.327466536 */, 17 }, + /* 2983 */ { MAD_F(0x053de717) /* 0.327612963 */, 17 }, + /* 2984 */ { MAD_F(0x053e80a6) /* 0.327759407 */, 17 }, + /* 2985 */ { MAD_F(0x053f1a39) /* 0.327905867 */, 17 }, + /* 2986 */ { MAD_F(0x053fb3d0) /* 0.328052344 */, 17 }, + /* 2987 */ { MAD_F(0x05404d6c) /* 0.328198837 */, 17 }, + /* 2988 */ { MAD_F(0x0540e70c) /* 0.328345346 */, 17 }, + /* 2989 */ { MAD_F(0x054180b1) /* 0.328491871 */, 17 }, + /* 2990 */ { MAD_F(0x05421a5a) /* 0.328638413 */, 17 }, + /* 2991 */ { MAD_F(0x0542b407) /* 0.328784971 */, 17 }, + + /* 2992 */ { MAD_F(0x05434db9) /* 0.328931546 */, 17 }, + /* 2993 */ { MAD_F(0x0543e76f) /* 0.329078137 */, 17 }, + /* 2994 */ { MAD_F(0x0544812a) /* 0.329224744 */, 17 }, + /* 2995 */ { MAD_F(0x05451ae9) /* 0.329371367 */, 17 }, + /* 2996 */ { MAD_F(0x0545b4ac) /* 0.329518007 */, 17 }, + /* 2997 */ { MAD_F(0x05464e74) /* 0.329664663 */, 17 }, + /* 2998 */ { MAD_F(0x0546e840) /* 0.329811336 */, 17 }, + /* 2999 */ { MAD_F(0x05478211) /* 0.329958024 */, 17 }, + /* 3000 */ { MAD_F(0x05481be5) /* 0.330104730 */, 17 }, + /* 3001 */ { MAD_F(0x0548b5bf) /* 0.330251451 */, 17 }, + /* 3002 */ { MAD_F(0x05494f9c) /* 0.330398189 */, 17 }, + /* 3003 */ { MAD_F(0x0549e97e) /* 0.330544943 */, 17 }, + /* 3004 */ { MAD_F(0x054a8364) /* 0.330691713 */, 17 }, + /* 3005 */ { MAD_F(0x054b1d4f) /* 0.330838499 */, 17 }, + /* 3006 */ { MAD_F(0x054bb73e) /* 0.330985302 */, 17 }, + /* 3007 */ { MAD_F(0x054c5132) /* 0.331132121 */, 17 }, + + /* 3008 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 17 }, + /* 3009 */ { MAD_F(0x054d8526) /* 0.331425808 */, 17 }, + /* 3010 */ { MAD_F(0x054e1f26) /* 0.331572676 */, 17 }, + /* 3011 */ { MAD_F(0x054eb92b) /* 0.331719560 */, 17 }, + /* 3012 */ { MAD_F(0x054f5334) /* 0.331866461 */, 17 }, + /* 3013 */ { MAD_F(0x054fed42) /* 0.332013377 */, 17 }, + /* 3014 */ { MAD_F(0x05508754) /* 0.332160310 */, 17 }, + /* 3015 */ { MAD_F(0x0551216b) /* 0.332307260 */, 17 }, + /* 3016 */ { MAD_F(0x0551bb85) /* 0.332454225 */, 17 }, + /* 3017 */ { MAD_F(0x055255a4) /* 0.332601207 */, 17 }, + /* 3018 */ { MAD_F(0x0552efc8) /* 0.332748205 */, 17 }, + /* 3019 */ { MAD_F(0x055389f0) /* 0.332895219 */, 17 }, + /* 3020 */ { MAD_F(0x0554241c) /* 0.333042249 */, 17 }, + /* 3021 */ { MAD_F(0x0554be4c) /* 0.333189296 */, 17 }, + /* 3022 */ { MAD_F(0x05555881) /* 0.333336359 */, 17 }, + /* 3023 */ { MAD_F(0x0555f2ba) /* 0.333483438 */, 17 }, + + /* 3024 */ { MAD_F(0x05568cf8) /* 0.333630533 */, 17 }, + /* 3025 */ { MAD_F(0x0557273a) /* 0.333777645 */, 17 }, + /* 3026 */ { MAD_F(0x0557c180) /* 0.333924772 */, 17 }, + /* 3027 */ { MAD_F(0x05585bcb) /* 0.334071916 */, 17 }, + /* 3028 */ { MAD_F(0x0558f61a) /* 0.334219076 */, 17 }, + /* 3029 */ { MAD_F(0x0559906d) /* 0.334366253 */, 17 }, + /* 3030 */ { MAD_F(0x055a2ac5) /* 0.334513445 */, 17 }, + /* 3031 */ { MAD_F(0x055ac521) /* 0.334660654 */, 17 }, + /* 3032 */ { MAD_F(0x055b5f81) /* 0.334807879 */, 17 }, + /* 3033 */ { MAD_F(0x055bf9e6) /* 0.334955120 */, 17 }, + /* 3034 */ { MAD_F(0x055c944f) /* 0.335102377 */, 17 }, + /* 3035 */ { MAD_F(0x055d2ebd) /* 0.335249651 */, 17 }, + /* 3036 */ { MAD_F(0x055dc92e) /* 0.335396941 */, 17 }, + /* 3037 */ { MAD_F(0x055e63a5) /* 0.335544246 */, 17 }, + /* 3038 */ { MAD_F(0x055efe1f) /* 0.335691568 */, 17 }, + /* 3039 */ { MAD_F(0x055f989e) /* 0.335838906 */, 17 }, + + /* 3040 */ { MAD_F(0x05603321) /* 0.335986261 */, 17 }, + /* 3041 */ { MAD_F(0x0560cda8) /* 0.336133631 */, 17 }, + /* 3042 */ { MAD_F(0x05616834) /* 0.336281018 */, 17 }, + /* 3043 */ { MAD_F(0x056202c4) /* 0.336428421 */, 17 }, + /* 3044 */ { MAD_F(0x05629d59) /* 0.336575840 */, 17 }, + /* 3045 */ { MAD_F(0x056337f2) /* 0.336723275 */, 17 }, + /* 3046 */ { MAD_F(0x0563d28f) /* 0.336870726 */, 17 }, + /* 3047 */ { MAD_F(0x05646d30) /* 0.337018193 */, 17 }, + /* 3048 */ { MAD_F(0x056507d6) /* 0.337165677 */, 17 }, + /* 3049 */ { MAD_F(0x0565a280) /* 0.337313176 */, 17 }, + /* 3050 */ { MAD_F(0x05663d2f) /* 0.337460692 */, 17 }, + /* 3051 */ { MAD_F(0x0566d7e1) /* 0.337608224 */, 17 }, + /* 3052 */ { MAD_F(0x05677298) /* 0.337755772 */, 17 }, + /* 3053 */ { MAD_F(0x05680d54) /* 0.337903336 */, 17 }, + /* 3054 */ { MAD_F(0x0568a814) /* 0.338050916 */, 17 }, + /* 3055 */ { MAD_F(0x056942d8) /* 0.338198513 */, 17 }, + + /* 3056 */ { MAD_F(0x0569dda0) /* 0.338346125 */, 17 }, + /* 3057 */ { MAD_F(0x056a786d) /* 0.338493753 */, 17 }, + /* 3058 */ { MAD_F(0x056b133e) /* 0.338641398 */, 17 }, + /* 3059 */ { MAD_F(0x056bae13) /* 0.338789059 */, 17 }, + /* 3060 */ { MAD_F(0x056c48ed) /* 0.338936736 */, 17 }, + /* 3061 */ { MAD_F(0x056ce3cb) /* 0.339084429 */, 17 }, + /* 3062 */ { MAD_F(0x056d7ead) /* 0.339232138 */, 17 }, + /* 3063 */ { MAD_F(0x056e1994) /* 0.339379863 */, 17 }, + /* 3064 */ { MAD_F(0x056eb47f) /* 0.339527604 */, 17 }, + /* 3065 */ { MAD_F(0x056f4f6e) /* 0.339675361 */, 17 }, + /* 3066 */ { MAD_F(0x056fea62) /* 0.339823134 */, 17 }, + /* 3067 */ { MAD_F(0x0570855a) /* 0.339970924 */, 17 }, + /* 3068 */ { MAD_F(0x05712056) /* 0.340118729 */, 17 }, + /* 3069 */ { MAD_F(0x0571bb56) /* 0.340266550 */, 17 }, + /* 3070 */ { MAD_F(0x0572565b) /* 0.340414388 */, 17 }, + /* 3071 */ { MAD_F(0x0572f164) /* 0.340562242 */, 17 }, + + /* 3072 */ { MAD_F(0x05738c72) /* 0.340710111 */, 17 }, + /* 3073 */ { MAD_F(0x05742784) /* 0.340857997 */, 17 }, + /* 3074 */ { MAD_F(0x0574c29a) /* 0.341005899 */, 17 }, + /* 3075 */ { MAD_F(0x05755db4) /* 0.341153816 */, 17 }, + /* 3076 */ { MAD_F(0x0575f8d3) /* 0.341301750 */, 17 }, + /* 3077 */ { MAD_F(0x057693f6) /* 0.341449700 */, 17 }, + /* 3078 */ { MAD_F(0x05772f1d) /* 0.341597666 */, 17 }, + /* 3079 */ { MAD_F(0x0577ca49) /* 0.341745648 */, 17 }, + /* 3080 */ { MAD_F(0x05786578) /* 0.341893646 */, 17 }, + /* 3081 */ { MAD_F(0x057900ad) /* 0.342041659 */, 17 }, + /* 3082 */ { MAD_F(0x05799be5) /* 0.342189689 */, 17 }, + /* 3083 */ { MAD_F(0x057a3722) /* 0.342337735 */, 17 }, + /* 3084 */ { MAD_F(0x057ad263) /* 0.342485797 */, 17 }, + /* 3085 */ { MAD_F(0x057b6da8) /* 0.342633875 */, 17 }, + /* 3086 */ { MAD_F(0x057c08f2) /* 0.342781969 */, 17 }, + /* 3087 */ { MAD_F(0x057ca440) /* 0.342930079 */, 17 }, + + /* 3088 */ { MAD_F(0x057d3f92) /* 0.343078205 */, 17 }, + /* 3089 */ { MAD_F(0x057ddae9) /* 0.343226347 */, 17 }, + /* 3090 */ { MAD_F(0x057e7644) /* 0.343374505 */, 17 }, + /* 3091 */ { MAD_F(0x057f11a3) /* 0.343522679 */, 17 }, + /* 3092 */ { MAD_F(0x057fad06) /* 0.343670869 */, 17 }, + /* 3093 */ { MAD_F(0x0580486e) /* 0.343819075 */, 17 }, + /* 3094 */ { MAD_F(0x0580e3da) /* 0.343967296 */, 17 }, + /* 3095 */ { MAD_F(0x05817f4a) /* 0.344115534 */, 17 }, + /* 3096 */ { MAD_F(0x05821abf) /* 0.344263788 */, 17 }, + /* 3097 */ { MAD_F(0x0582b638) /* 0.344412058 */, 17 }, + /* 3098 */ { MAD_F(0x058351b5) /* 0.344560343 */, 17 }, + /* 3099 */ { MAD_F(0x0583ed36) /* 0.344708645 */, 17 }, + /* 3100 */ { MAD_F(0x058488bc) /* 0.344856963 */, 17 }, + /* 3101 */ { MAD_F(0x05852446) /* 0.345005296 */, 17 }, + /* 3102 */ { MAD_F(0x0585bfd4) /* 0.345153646 */, 17 }, + /* 3103 */ { MAD_F(0x05865b67) /* 0.345302011 */, 17 }, + + /* 3104 */ { MAD_F(0x0586f6fd) /* 0.345450393 */, 17 }, + /* 3105 */ { MAD_F(0x05879298) /* 0.345598790 */, 17 }, + /* 3106 */ { MAD_F(0x05882e38) /* 0.345747203 */, 17 }, + /* 3107 */ { MAD_F(0x0588c9dc) /* 0.345895632 */, 17 }, + /* 3108 */ { MAD_F(0x05896583) /* 0.346044077 */, 17 }, + /* 3109 */ { MAD_F(0x058a0130) /* 0.346192538 */, 17 }, + /* 3110 */ { MAD_F(0x058a9ce0) /* 0.346341015 */, 17 }, + /* 3111 */ { MAD_F(0x058b3895) /* 0.346489508 */, 17 }, + /* 3112 */ { MAD_F(0x058bd44e) /* 0.346638017 */, 17 }, + /* 3113 */ { MAD_F(0x058c700b) /* 0.346786542 */, 17 }, + /* 3114 */ { MAD_F(0x058d0bcd) /* 0.346935082 */, 17 }, + /* 3115 */ { MAD_F(0x058da793) /* 0.347083639 */, 17 }, + /* 3116 */ { MAD_F(0x058e435d) /* 0.347232211 */, 17 }, + /* 3117 */ { MAD_F(0x058edf2b) /* 0.347380799 */, 17 }, + /* 3118 */ { MAD_F(0x058f7afe) /* 0.347529403 */, 17 }, + /* 3119 */ { MAD_F(0x059016d5) /* 0.347678023 */, 17 }, + + /* 3120 */ { MAD_F(0x0590b2b0) /* 0.347826659 */, 17 }, + /* 3121 */ { MAD_F(0x05914e8f) /* 0.347975311 */, 17 }, + /* 3122 */ { MAD_F(0x0591ea73) /* 0.348123979 */, 17 }, + /* 3123 */ { MAD_F(0x0592865b) /* 0.348272662 */, 17 }, + /* 3124 */ { MAD_F(0x05932247) /* 0.348421362 */, 17 }, + /* 3125 */ { MAD_F(0x0593be37) /* 0.348570077 */, 17 }, + /* 3126 */ { MAD_F(0x05945a2c) /* 0.348718808 */, 17 }, + /* 3127 */ { MAD_F(0x0594f625) /* 0.348867555 */, 17 }, + /* 3128 */ { MAD_F(0x05959222) /* 0.349016318 */, 17 }, + /* 3129 */ { MAD_F(0x05962e24) /* 0.349165097 */, 17 }, + /* 3130 */ { MAD_F(0x0596ca2a) /* 0.349313892 */, 17 }, + /* 3131 */ { MAD_F(0x05976634) /* 0.349462702 */, 17 }, + /* 3132 */ { MAD_F(0x05980242) /* 0.349611528 */, 17 }, + /* 3133 */ { MAD_F(0x05989e54) /* 0.349760370 */, 17 }, + /* 3134 */ { MAD_F(0x05993a6b) /* 0.349909228 */, 17 }, + /* 3135 */ { MAD_F(0x0599d686) /* 0.350058102 */, 17 }, + + /* 3136 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 17 }, + /* 3137 */ { MAD_F(0x059b0ec9) /* 0.350355897 */, 17 }, + /* 3138 */ { MAD_F(0x059baaf1) /* 0.350504818 */, 17 }, + /* 3139 */ { MAD_F(0x059c471d) /* 0.350653756 */, 17 }, + /* 3140 */ { MAD_F(0x059ce34d) /* 0.350802708 */, 17 }, + /* 3141 */ { MAD_F(0x059d7f81) /* 0.350951677 */, 17 }, + /* 3142 */ { MAD_F(0x059e1bba) /* 0.351100662 */, 17 }, + /* 3143 */ { MAD_F(0x059eb7f7) /* 0.351249662 */, 17 }, + /* 3144 */ { MAD_F(0x059f5438) /* 0.351398678 */, 17 }, + /* 3145 */ { MAD_F(0x059ff07e) /* 0.351547710 */, 17 }, + /* 3146 */ { MAD_F(0x05a08cc7) /* 0.351696758 */, 17 }, + /* 3147 */ { MAD_F(0x05a12915) /* 0.351845821 */, 17 }, + /* 3148 */ { MAD_F(0x05a1c567) /* 0.351994901 */, 17 }, + /* 3149 */ { MAD_F(0x05a261be) /* 0.352143996 */, 17 }, + /* 3150 */ { MAD_F(0x05a2fe18) /* 0.352293107 */, 17 }, + /* 3151 */ { MAD_F(0x05a39a77) /* 0.352442233 */, 17 }, + + /* 3152 */ { MAD_F(0x05a436da) /* 0.352591376 */, 17 }, + /* 3153 */ { MAD_F(0x05a4d342) /* 0.352740534 */, 17 }, + /* 3154 */ { MAD_F(0x05a56fad) /* 0.352889708 */, 17 }, + /* 3155 */ { MAD_F(0x05a60c1d) /* 0.353038898 */, 17 }, + /* 3156 */ { MAD_F(0x05a6a891) /* 0.353188103 */, 17 }, + /* 3157 */ { MAD_F(0x05a7450a) /* 0.353337325 */, 17 }, + /* 3158 */ { MAD_F(0x05a7e186) /* 0.353486562 */, 17 }, + /* 3159 */ { MAD_F(0x05a87e07) /* 0.353635814 */, 17 }, + /* 3160 */ { MAD_F(0x05a91a8c) /* 0.353785083 */, 17 }, + /* 3161 */ { MAD_F(0x05a9b715) /* 0.353934367 */, 17 }, + /* 3162 */ { MAD_F(0x05aa53a2) /* 0.354083667 */, 17 }, + /* 3163 */ { MAD_F(0x05aaf034) /* 0.354232983 */, 17 }, + /* 3164 */ { MAD_F(0x05ab8cca) /* 0.354382314 */, 17 }, + /* 3165 */ { MAD_F(0x05ac2964) /* 0.354531662 */, 17 }, + /* 3166 */ { MAD_F(0x05acc602) /* 0.354681025 */, 17 }, + /* 3167 */ { MAD_F(0x05ad62a5) /* 0.354830403 */, 17 }, + + /* 3168 */ { MAD_F(0x05adff4c) /* 0.354979798 */, 17 }, + /* 3169 */ { MAD_F(0x05ae9bf7) /* 0.355129208 */, 17 }, + /* 3170 */ { MAD_F(0x05af38a6) /* 0.355278634 */, 17 }, + /* 3171 */ { MAD_F(0x05afd559) /* 0.355428075 */, 17 }, + /* 3172 */ { MAD_F(0x05b07211) /* 0.355577533 */, 17 }, + /* 3173 */ { MAD_F(0x05b10ecd) /* 0.355727006 */, 17 }, + /* 3174 */ { MAD_F(0x05b1ab8d) /* 0.355876494 */, 17 }, + /* 3175 */ { MAD_F(0x05b24851) /* 0.356025999 */, 17 }, + /* 3176 */ { MAD_F(0x05b2e51a) /* 0.356175519 */, 17 }, + /* 3177 */ { MAD_F(0x05b381e6) /* 0.356325054 */, 17 }, + /* 3178 */ { MAD_F(0x05b41eb7) /* 0.356474606 */, 17 }, + /* 3179 */ { MAD_F(0x05b4bb8c) /* 0.356624173 */, 17 }, + /* 3180 */ { MAD_F(0x05b55866) /* 0.356773756 */, 17 }, + /* 3181 */ { MAD_F(0x05b5f543) /* 0.356923354 */, 17 }, + /* 3182 */ { MAD_F(0x05b69225) /* 0.357072969 */, 17 }, + /* 3183 */ { MAD_F(0x05b72f0b) /* 0.357222598 */, 17 }, + + /* 3184 */ { MAD_F(0x05b7cbf5) /* 0.357372244 */, 17 }, + /* 3185 */ { MAD_F(0x05b868e3) /* 0.357521905 */, 17 }, + /* 3186 */ { MAD_F(0x05b905d6) /* 0.357671582 */, 17 }, + /* 3187 */ { MAD_F(0x05b9a2cd) /* 0.357821275 */, 17 }, + /* 3188 */ { MAD_F(0x05ba3fc8) /* 0.357970983 */, 17 }, + /* 3189 */ { MAD_F(0x05badcc7) /* 0.358120707 */, 17 }, + /* 3190 */ { MAD_F(0x05bb79ca) /* 0.358270446 */, 17 }, + /* 3191 */ { MAD_F(0x05bc16d2) /* 0.358420201 */, 17 }, + /* 3192 */ { MAD_F(0x05bcb3de) /* 0.358569972 */, 17 }, + /* 3193 */ { MAD_F(0x05bd50ee) /* 0.358719758 */, 17 }, + /* 3194 */ { MAD_F(0x05bdee02) /* 0.358869560 */, 17 }, + /* 3195 */ { MAD_F(0x05be8b1a) /* 0.359019378 */, 17 }, + /* 3196 */ { MAD_F(0x05bf2837) /* 0.359169211 */, 17 }, + /* 3197 */ { MAD_F(0x05bfc558) /* 0.359319060 */, 17 }, + /* 3198 */ { MAD_F(0x05c0627d) /* 0.359468925 */, 17 }, + /* 3199 */ { MAD_F(0x05c0ffa6) /* 0.359618805 */, 17 }, + + /* 3200 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 17 }, + /* 3201 */ { MAD_F(0x05c23a05) /* 0.359918612 */, 17 }, + /* 3202 */ { MAD_F(0x05c2d73a) /* 0.360068540 */, 17 }, + /* 3203 */ { MAD_F(0x05c37474) /* 0.360218482 */, 17 }, + /* 3204 */ { MAD_F(0x05c411b2) /* 0.360368440 */, 17 }, + /* 3205 */ { MAD_F(0x05c4aef5) /* 0.360518414 */, 17 }, + /* 3206 */ { MAD_F(0x05c54c3b) /* 0.360668404 */, 17 }, + /* 3207 */ { MAD_F(0x05c5e986) /* 0.360818409 */, 17 }, + /* 3208 */ { MAD_F(0x05c686d5) /* 0.360968429 */, 17 }, + /* 3209 */ { MAD_F(0x05c72428) /* 0.361118466 */, 17 }, + /* 3210 */ { MAD_F(0x05c7c17f) /* 0.361268517 */, 17 }, + /* 3211 */ { MAD_F(0x05c85eda) /* 0.361418585 */, 17 }, + /* 3212 */ { MAD_F(0x05c8fc3a) /* 0.361568668 */, 17 }, + /* 3213 */ { MAD_F(0x05c9999e) /* 0.361718766 */, 17 }, + /* 3214 */ { MAD_F(0x05ca3706) /* 0.361868881 */, 17 }, + /* 3215 */ { MAD_F(0x05cad472) /* 0.362019010 */, 17 }, + + /* 3216 */ { MAD_F(0x05cb71e2) /* 0.362169156 */, 17 }, + /* 3217 */ { MAD_F(0x05cc0f57) /* 0.362319316 */, 17 }, + /* 3218 */ { MAD_F(0x05ccaccf) /* 0.362469493 */, 17 }, + /* 3219 */ { MAD_F(0x05cd4a4c) /* 0.362619685 */, 17 }, + /* 3220 */ { MAD_F(0x05cde7cd) /* 0.362769892 */, 17 }, + /* 3221 */ { MAD_F(0x05ce8552) /* 0.362920115 */, 17 }, + /* 3222 */ { MAD_F(0x05cf22dc) /* 0.363070354 */, 17 }, + /* 3223 */ { MAD_F(0x05cfc069) /* 0.363220608 */, 17 }, + /* 3224 */ { MAD_F(0x05d05dfb) /* 0.363370878 */, 17 }, + /* 3225 */ { MAD_F(0x05d0fb91) /* 0.363521163 */, 17 }, + /* 3226 */ { MAD_F(0x05d1992b) /* 0.363671464 */, 17 }, + /* 3227 */ { MAD_F(0x05d236c9) /* 0.363821780 */, 17 }, + /* 3228 */ { MAD_F(0x05d2d46c) /* 0.363972112 */, 17 }, + /* 3229 */ { MAD_F(0x05d37212) /* 0.364122459 */, 17 }, + /* 3230 */ { MAD_F(0x05d40fbd) /* 0.364272822 */, 17 }, + /* 3231 */ { MAD_F(0x05d4ad6c) /* 0.364423200 */, 17 }, + + /* 3232 */ { MAD_F(0x05d54b1f) /* 0.364573594 */, 17 }, + /* 3233 */ { MAD_F(0x05d5e8d6) /* 0.364724004 */, 17 }, + /* 3234 */ { MAD_F(0x05d68691) /* 0.364874429 */, 17 }, + /* 3235 */ { MAD_F(0x05d72451) /* 0.365024869 */, 17 }, + /* 3236 */ { MAD_F(0x05d7c215) /* 0.365175325 */, 17 }, + /* 3237 */ { MAD_F(0x05d85fdc) /* 0.365325796 */, 17 }, + /* 3238 */ { MAD_F(0x05d8fda8) /* 0.365476283 */, 17 }, + /* 3239 */ { MAD_F(0x05d99b79) /* 0.365626786 */, 17 }, + /* 3240 */ { MAD_F(0x05da394d) /* 0.365777304 */, 17 }, + /* 3241 */ { MAD_F(0x05dad726) /* 0.365927837 */, 17 }, + /* 3242 */ { MAD_F(0x05db7502) /* 0.366078386 */, 17 }, + /* 3243 */ { MAD_F(0x05dc12e3) /* 0.366228950 */, 17 }, + /* 3244 */ { MAD_F(0x05dcb0c8) /* 0.366379530 */, 17 }, + /* 3245 */ { MAD_F(0x05dd4eb1) /* 0.366530125 */, 17 }, + /* 3246 */ { MAD_F(0x05ddec9e) /* 0.366680736 */, 17 }, + /* 3247 */ { MAD_F(0x05de8a90) /* 0.366831362 */, 17 }, + + /* 3248 */ { MAD_F(0x05df2885) /* 0.366982004 */, 17 }, + /* 3249 */ { MAD_F(0x05dfc67f) /* 0.367132661 */, 17 }, + /* 3250 */ { MAD_F(0x05e0647d) /* 0.367283334 */, 17 }, + /* 3251 */ { MAD_F(0x05e1027f) /* 0.367434022 */, 17 }, + /* 3252 */ { MAD_F(0x05e1a085) /* 0.367584725 */, 17 }, + /* 3253 */ { MAD_F(0x05e23e8f) /* 0.367735444 */, 17 }, + /* 3254 */ { MAD_F(0x05e2dc9e) /* 0.367886179 */, 17 }, + /* 3255 */ { MAD_F(0x05e37ab0) /* 0.368036929 */, 17 }, + /* 3256 */ { MAD_F(0x05e418c7) /* 0.368187694 */, 17 }, + /* 3257 */ { MAD_F(0x05e4b6e2) /* 0.368338475 */, 17 }, + /* 3258 */ { MAD_F(0x05e55501) /* 0.368489271 */, 17 }, + /* 3259 */ { MAD_F(0x05e5f324) /* 0.368640082 */, 17 }, + /* 3260 */ { MAD_F(0x05e6914c) /* 0.368790909 */, 17 }, + /* 3261 */ { MAD_F(0x05e72f77) /* 0.368941752 */, 17 }, + /* 3262 */ { MAD_F(0x05e7cda7) /* 0.369092610 */, 17 }, + /* 3263 */ { MAD_F(0x05e86bda) /* 0.369243483 */, 17 }, + + /* 3264 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 17 }, + /* 3265 */ { MAD_F(0x05e9a84e) /* 0.369545276 */, 17 }, + /* 3266 */ { MAD_F(0x05ea468e) /* 0.369696195 */, 17 }, + /* 3267 */ { MAD_F(0x05eae4d3) /* 0.369847130 */, 17 }, + /* 3268 */ { MAD_F(0x05eb831b) /* 0.369998080 */, 17 }, + /* 3269 */ { MAD_F(0x05ec2168) /* 0.370149046 */, 17 }, + /* 3270 */ { MAD_F(0x05ecbfb8) /* 0.370300027 */, 17 }, + /* 3271 */ { MAD_F(0x05ed5e0d) /* 0.370451024 */, 17 }, + /* 3272 */ { MAD_F(0x05edfc66) /* 0.370602036 */, 17 }, + /* 3273 */ { MAD_F(0x05ee9ac3) /* 0.370753063 */, 17 }, + /* 3274 */ { MAD_F(0x05ef3924) /* 0.370904105 */, 17 }, + /* 3275 */ { MAD_F(0x05efd78a) /* 0.371055163 */, 17 }, + /* 3276 */ { MAD_F(0x05f075f3) /* 0.371206237 */, 17 }, + /* 3277 */ { MAD_F(0x05f11461) /* 0.371357326 */, 17 }, + /* 3278 */ { MAD_F(0x05f1b2d3) /* 0.371508430 */, 17 }, + /* 3279 */ { MAD_F(0x05f25148) /* 0.371659549 */, 17 }, + + /* 3280 */ { MAD_F(0x05f2efc2) /* 0.371810684 */, 17 }, + /* 3281 */ { MAD_F(0x05f38e40) /* 0.371961834 */, 17 }, + /* 3282 */ { MAD_F(0x05f42cc3) /* 0.372113000 */, 17 }, + /* 3283 */ { MAD_F(0x05f4cb49) /* 0.372264181 */, 17 }, + /* 3284 */ { MAD_F(0x05f569d3) /* 0.372415377 */, 17 }, + /* 3285 */ { MAD_F(0x05f60862) /* 0.372566589 */, 17 }, + /* 3286 */ { MAD_F(0x05f6a6f5) /* 0.372717816 */, 17 }, + /* 3287 */ { MAD_F(0x05f7458b) /* 0.372869058 */, 17 }, + /* 3288 */ { MAD_F(0x05f7e426) /* 0.373020316 */, 17 }, + /* 3289 */ { MAD_F(0x05f882c5) /* 0.373171589 */, 17 }, + /* 3290 */ { MAD_F(0x05f92169) /* 0.373322877 */, 17 }, + /* 3291 */ { MAD_F(0x05f9c010) /* 0.373474181 */, 17 }, + /* 3292 */ { MAD_F(0x05fa5ebb) /* 0.373625500 */, 17 }, + /* 3293 */ { MAD_F(0x05fafd6b) /* 0.373776834 */, 17 }, + /* 3294 */ { MAD_F(0x05fb9c1e) /* 0.373928184 */, 17 }, + /* 3295 */ { MAD_F(0x05fc3ad6) /* 0.374079549 */, 17 }, + + /* 3296 */ { MAD_F(0x05fcd992) /* 0.374230929 */, 17 }, + /* 3297 */ { MAD_F(0x05fd7852) /* 0.374382325 */, 17 }, + /* 3298 */ { MAD_F(0x05fe1716) /* 0.374533735 */, 17 }, + /* 3299 */ { MAD_F(0x05feb5de) /* 0.374685162 */, 17 }, + /* 3300 */ { MAD_F(0x05ff54aa) /* 0.374836603 */, 17 }, + /* 3301 */ { MAD_F(0x05fff37b) /* 0.374988060 */, 17 }, + /* 3302 */ { MAD_F(0x0600924f) /* 0.375139532 */, 17 }, + /* 3303 */ { MAD_F(0x06013128) /* 0.375291019 */, 17 }, + /* 3304 */ { MAD_F(0x0601d004) /* 0.375442522 */, 17 }, + /* 3305 */ { MAD_F(0x06026ee5) /* 0.375594040 */, 17 }, + /* 3306 */ { MAD_F(0x06030dca) /* 0.375745573 */, 17 }, + /* 3307 */ { MAD_F(0x0603acb3) /* 0.375897122 */, 17 }, + /* 3308 */ { MAD_F(0x06044ba0) /* 0.376048685 */, 17 }, + /* 3309 */ { MAD_F(0x0604ea91) /* 0.376200265 */, 17 }, + /* 3310 */ { MAD_F(0x06058987) /* 0.376351859 */, 17 }, + /* 3311 */ { MAD_F(0x06062880) /* 0.376503468 */, 17 }, + + /* 3312 */ { MAD_F(0x0606c77d) /* 0.376655093 */, 17 }, + /* 3313 */ { MAD_F(0x0607667f) /* 0.376806733 */, 17 }, + /* 3314 */ { MAD_F(0x06080585) /* 0.376958389 */, 17 }, + /* 3315 */ { MAD_F(0x0608a48f) /* 0.377110059 */, 17 }, + /* 3316 */ { MAD_F(0x0609439c) /* 0.377261745 */, 17 }, + /* 3317 */ { MAD_F(0x0609e2ae) /* 0.377413446 */, 17 }, + /* 3318 */ { MAD_F(0x060a81c4) /* 0.377565163 */, 17 }, + /* 3319 */ { MAD_F(0x060b20df) /* 0.377716894 */, 17 }, + /* 3320 */ { MAD_F(0x060bbffd) /* 0.377868641 */, 17 }, + /* 3321 */ { MAD_F(0x060c5f1f) /* 0.378020403 */, 17 }, + /* 3322 */ { MAD_F(0x060cfe46) /* 0.378172181 */, 17 }, + /* 3323 */ { MAD_F(0x060d9d70) /* 0.378323973 */, 17 }, + /* 3324 */ { MAD_F(0x060e3c9f) /* 0.378475781 */, 17 }, + /* 3325 */ { MAD_F(0x060edbd1) /* 0.378627604 */, 17 }, + /* 3326 */ { MAD_F(0x060f7b08) /* 0.378779442 */, 17 }, + /* 3327 */ { MAD_F(0x06101a43) /* 0.378931296 */, 17 }, + + /* 3328 */ { MAD_F(0x0610b982) /* 0.379083164 */, 17 }, + /* 3329 */ { MAD_F(0x061158c5) /* 0.379235048 */, 17 }, + /* 3330 */ { MAD_F(0x0611f80c) /* 0.379386947 */, 17 }, + /* 3331 */ { MAD_F(0x06129757) /* 0.379538862 */, 17 }, + /* 3332 */ { MAD_F(0x061336a6) /* 0.379690791 */, 17 }, + /* 3333 */ { MAD_F(0x0613d5fa) /* 0.379842736 */, 17 }, + /* 3334 */ { MAD_F(0x06147551) /* 0.379994696 */, 17 }, + /* 3335 */ { MAD_F(0x061514ad) /* 0.380146671 */, 17 }, + /* 3336 */ { MAD_F(0x0615b40c) /* 0.380298661 */, 17 }, + /* 3337 */ { MAD_F(0x06165370) /* 0.380450666 */, 17 }, + /* 3338 */ { MAD_F(0x0616f2d8) /* 0.380602687 */, 17 }, + /* 3339 */ { MAD_F(0x06179243) /* 0.380754723 */, 17 }, + /* 3340 */ { MAD_F(0x061831b3) /* 0.380906774 */, 17 }, + /* 3341 */ { MAD_F(0x0618d127) /* 0.381058840 */, 17 }, + /* 3342 */ { MAD_F(0x0619709f) /* 0.381210921 */, 17 }, + /* 3343 */ { MAD_F(0x061a101b) /* 0.381363018 */, 17 }, + + /* 3344 */ { MAD_F(0x061aaf9c) /* 0.381515130 */, 17 }, + /* 3345 */ { MAD_F(0x061b4f20) /* 0.381667257 */, 17 }, + /* 3346 */ { MAD_F(0x061beea8) /* 0.381819399 */, 17 }, + /* 3347 */ { MAD_F(0x061c8e34) /* 0.381971556 */, 17 }, + /* 3348 */ { MAD_F(0x061d2dc5) /* 0.382123728 */, 17 }, + /* 3349 */ { MAD_F(0x061dcd59) /* 0.382275916 */, 17 }, + /* 3350 */ { MAD_F(0x061e6cf2) /* 0.382428118 */, 17 }, + /* 3351 */ { MAD_F(0x061f0c8f) /* 0.382580336 */, 17 }, + /* 3352 */ { MAD_F(0x061fac2f) /* 0.382732569 */, 17 }, + /* 3353 */ { MAD_F(0x06204bd4) /* 0.382884817 */, 17 }, + /* 3354 */ { MAD_F(0x0620eb7d) /* 0.383037080 */, 17 }, + /* 3355 */ { MAD_F(0x06218b2a) /* 0.383189358 */, 17 }, + /* 3356 */ { MAD_F(0x06222adb) /* 0.383341652 */, 17 }, + /* 3357 */ { MAD_F(0x0622ca90) /* 0.383493960 */, 17 }, + /* 3358 */ { MAD_F(0x06236a49) /* 0.383646284 */, 17 }, + /* 3359 */ { MAD_F(0x06240a06) /* 0.383798623 */, 17 }, + + /* 3360 */ { MAD_F(0x0624a9c7) /* 0.383950977 */, 17 }, + /* 3361 */ { MAD_F(0x0625498d) /* 0.384103346 */, 17 }, + /* 3362 */ { MAD_F(0x0625e956) /* 0.384255730 */, 17 }, + /* 3363 */ { MAD_F(0x06268923) /* 0.384408129 */, 17 }, + /* 3364 */ { MAD_F(0x062728f5) /* 0.384560544 */, 17 }, + /* 3365 */ { MAD_F(0x0627c8ca) /* 0.384712973 */, 17 }, + /* 3366 */ { MAD_F(0x062868a4) /* 0.384865418 */, 17 }, + /* 3367 */ { MAD_F(0x06290881) /* 0.385017878 */, 17 }, + /* 3368 */ { MAD_F(0x0629a863) /* 0.385170352 */, 17 }, + /* 3369 */ { MAD_F(0x062a4849) /* 0.385322842 */, 17 }, + /* 3370 */ { MAD_F(0x062ae832) /* 0.385475347 */, 17 }, + /* 3371 */ { MAD_F(0x062b8820) /* 0.385627867 */, 17 }, + /* 3372 */ { MAD_F(0x062c2812) /* 0.385780402 */, 17 }, + /* 3373 */ { MAD_F(0x062cc808) /* 0.385932953 */, 17 }, + /* 3374 */ { MAD_F(0x062d6802) /* 0.386085518 */, 17 }, + /* 3375 */ { MAD_F(0x062e0800) /* 0.386238098 */, 17 }, + + /* 3376 */ { MAD_F(0x062ea802) /* 0.386390694 */, 17 }, + /* 3377 */ { MAD_F(0x062f4808) /* 0.386543304 */, 17 }, + /* 3378 */ { MAD_F(0x062fe812) /* 0.386695930 */, 17 }, + /* 3379 */ { MAD_F(0x06308820) /* 0.386848570 */, 17 }, + /* 3380 */ { MAD_F(0x06312832) /* 0.387001226 */, 17 }, + /* 3381 */ { MAD_F(0x0631c849) /* 0.387153897 */, 17 }, + /* 3382 */ { MAD_F(0x06326863) /* 0.387306582 */, 17 }, + /* 3383 */ { MAD_F(0x06330881) /* 0.387459283 */, 17 }, + /* 3384 */ { MAD_F(0x0633a8a3) /* 0.387611999 */, 17 }, + /* 3385 */ { MAD_F(0x063448ca) /* 0.387764730 */, 17 }, + /* 3386 */ { MAD_F(0x0634e8f4) /* 0.387917476 */, 17 }, + /* 3387 */ { MAD_F(0x06358923) /* 0.388070237 */, 17 }, + /* 3388 */ { MAD_F(0x06362955) /* 0.388223013 */, 17 }, + /* 3389 */ { MAD_F(0x0636c98c) /* 0.388375804 */, 17 }, + /* 3390 */ { MAD_F(0x063769c6) /* 0.388528610 */, 17 }, + /* 3391 */ { MAD_F(0x06380a05) /* 0.388681431 */, 17 }, + + /* 3392 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 17 }, + /* 3393 */ { MAD_F(0x06394a8e) /* 0.388987119 */, 17 }, + /* 3394 */ { MAD_F(0x0639ead9) /* 0.389139985 */, 17 }, + /* 3395 */ { MAD_F(0x063a8b28) /* 0.389292866 */, 17 }, + /* 3396 */ { MAD_F(0x063b2b7b) /* 0.389445762 */, 17 }, + /* 3397 */ { MAD_F(0x063bcbd1) /* 0.389598674 */, 17 }, + /* 3398 */ { MAD_F(0x063c6c2c) /* 0.389751600 */, 17 }, + /* 3399 */ { MAD_F(0x063d0c8b) /* 0.389904541 */, 17 }, + /* 3400 */ { MAD_F(0x063dacee) /* 0.390057497 */, 17 }, + /* 3401 */ { MAD_F(0x063e4d55) /* 0.390210468 */, 17 }, + /* 3402 */ { MAD_F(0x063eedc0) /* 0.390363455 */, 17 }, + /* 3403 */ { MAD_F(0x063f8e2f) /* 0.390516456 */, 17 }, + /* 3404 */ { MAD_F(0x06402ea2) /* 0.390669472 */, 17 }, + /* 3405 */ { MAD_F(0x0640cf19) /* 0.390822503 */, 17 }, + /* 3406 */ { MAD_F(0x06416f94) /* 0.390975549 */, 17 }, + /* 3407 */ { MAD_F(0x06421013) /* 0.391128611 */, 17 }, + + /* 3408 */ { MAD_F(0x0642b096) /* 0.391281687 */, 17 }, + /* 3409 */ { MAD_F(0x0643511d) /* 0.391434778 */, 17 }, + /* 3410 */ { MAD_F(0x0643f1a8) /* 0.391587884 */, 17 }, + /* 3411 */ { MAD_F(0x06449237) /* 0.391741005 */, 17 }, + /* 3412 */ { MAD_F(0x064532ca) /* 0.391894141 */, 17 }, + /* 3413 */ { MAD_F(0x0645d361) /* 0.392047292 */, 17 }, + /* 3414 */ { MAD_F(0x064673fc) /* 0.392200458 */, 17 }, + /* 3415 */ { MAD_F(0x0647149c) /* 0.392353638 */, 17 }, + /* 3416 */ { MAD_F(0x0647b53f) /* 0.392506834 */, 17 }, + /* 3417 */ { MAD_F(0x064855e6) /* 0.392660045 */, 17 }, + /* 3418 */ { MAD_F(0x0648f691) /* 0.392813271 */, 17 }, + /* 3419 */ { MAD_F(0x06499740) /* 0.392966511 */, 17 }, + /* 3420 */ { MAD_F(0x064a37f4) /* 0.393119767 */, 17 }, + /* 3421 */ { MAD_F(0x064ad8ab) /* 0.393273038 */, 17 }, + /* 3422 */ { MAD_F(0x064b7966) /* 0.393426323 */, 17 }, + /* 3423 */ { MAD_F(0x064c1a25) /* 0.393579623 */, 17 }, + + /* 3424 */ { MAD_F(0x064cbae9) /* 0.393732939 */, 17 }, + /* 3425 */ { MAD_F(0x064d5bb0) /* 0.393886269 */, 17 }, + /* 3426 */ { MAD_F(0x064dfc7b) /* 0.394039614 */, 17 }, + /* 3427 */ { MAD_F(0x064e9d4b) /* 0.394192974 */, 17 }, + /* 3428 */ { MAD_F(0x064f3e1e) /* 0.394346349 */, 17 }, + /* 3429 */ { MAD_F(0x064fdef5) /* 0.394499739 */, 17 }, + /* 3430 */ { MAD_F(0x06507fd0) /* 0.394653144 */, 17 }, + /* 3431 */ { MAD_F(0x065120b0) /* 0.394806564 */, 17 }, + /* 3432 */ { MAD_F(0x0651c193) /* 0.394959999 */, 17 }, + /* 3433 */ { MAD_F(0x0652627a) /* 0.395113448 */, 17 }, + /* 3434 */ { MAD_F(0x06530366) /* 0.395266913 */, 17 }, + /* 3435 */ { MAD_F(0x0653a455) /* 0.395420392 */, 17 }, + /* 3436 */ { MAD_F(0x06544548) /* 0.395573886 */, 17 }, + /* 3437 */ { MAD_F(0x0654e640) /* 0.395727395 */, 17 }, + /* 3438 */ { MAD_F(0x0655873b) /* 0.395880919 */, 17 }, + /* 3439 */ { MAD_F(0x0656283a) /* 0.396034458 */, 17 }, + + /* 3440 */ { MAD_F(0x0656c93d) /* 0.396188012 */, 17 }, + /* 3441 */ { MAD_F(0x06576a45) /* 0.396341581 */, 17 }, + /* 3442 */ { MAD_F(0x06580b50) /* 0.396495164 */, 17 }, + /* 3443 */ { MAD_F(0x0658ac5f) /* 0.396648763 */, 17 }, + /* 3444 */ { MAD_F(0x06594d73) /* 0.396802376 */, 17 }, + /* 3445 */ { MAD_F(0x0659ee8a) /* 0.396956004 */, 17 }, + /* 3446 */ { MAD_F(0x065a8fa5) /* 0.397109647 */, 17 }, + /* 3447 */ { MAD_F(0x065b30c4) /* 0.397263305 */, 17 }, + /* 3448 */ { MAD_F(0x065bd1e7) /* 0.397416978 */, 17 }, + /* 3449 */ { MAD_F(0x065c730f) /* 0.397570666 */, 17 }, + /* 3450 */ { MAD_F(0x065d143a) /* 0.397724368 */, 17 }, + /* 3451 */ { MAD_F(0x065db569) /* 0.397878085 */, 17 }, + /* 3452 */ { MAD_F(0x065e569c) /* 0.398031818 */, 17 }, + /* 3453 */ { MAD_F(0x065ef7d3) /* 0.398185565 */, 17 }, + /* 3454 */ { MAD_F(0x065f990e) /* 0.398339326 */, 17 }, + /* 3455 */ { MAD_F(0x06603a4e) /* 0.398493103 */, 17 }, + + /* 3456 */ { MAD_F(0x0660db91) /* 0.398646895 */, 17 }, + /* 3457 */ { MAD_F(0x06617cd8) /* 0.398800701 */, 17 }, + /* 3458 */ { MAD_F(0x06621e23) /* 0.398954522 */, 17 }, + /* 3459 */ { MAD_F(0x0662bf72) /* 0.399108358 */, 17 }, + /* 3460 */ { MAD_F(0x066360c5) /* 0.399262209 */, 17 }, + /* 3461 */ { MAD_F(0x0664021c) /* 0.399416075 */, 17 }, + /* 3462 */ { MAD_F(0x0664a377) /* 0.399569955 */, 17 }, + /* 3463 */ { MAD_F(0x066544d6) /* 0.399723851 */, 17 }, + /* 3464 */ { MAD_F(0x0665e639) /* 0.399877761 */, 17 }, + /* 3465 */ { MAD_F(0x066687a0) /* 0.400031686 */, 17 }, + /* 3466 */ { MAD_F(0x0667290b) /* 0.400185625 */, 17 }, + /* 3467 */ { MAD_F(0x0667ca79) /* 0.400339580 */, 17 }, + /* 3468 */ { MAD_F(0x06686bec) /* 0.400493549 */, 17 }, + /* 3469 */ { MAD_F(0x06690d63) /* 0.400647534 */, 17 }, + /* 3470 */ { MAD_F(0x0669aede) /* 0.400801533 */, 17 }, + /* 3471 */ { MAD_F(0x066a505d) /* 0.400955546 */, 17 }, + + /* 3472 */ { MAD_F(0x066af1df) /* 0.401109575 */, 17 }, + /* 3473 */ { MAD_F(0x066b9366) /* 0.401263618 */, 17 }, + /* 3474 */ { MAD_F(0x066c34f1) /* 0.401417676 */, 17 }, + /* 3475 */ { MAD_F(0x066cd67f) /* 0.401571749 */, 17 }, + /* 3476 */ { MAD_F(0x066d7812) /* 0.401725837 */, 17 }, + /* 3477 */ { MAD_F(0x066e19a9) /* 0.401879939 */, 17 }, + /* 3478 */ { MAD_F(0x066ebb43) /* 0.402034056 */, 17 }, + /* 3479 */ { MAD_F(0x066f5ce2) /* 0.402188188 */, 17 }, + /* 3480 */ { MAD_F(0x066ffe84) /* 0.402342335 */, 17 }, + /* 3481 */ { MAD_F(0x0670a02a) /* 0.402496497 */, 17 }, + /* 3482 */ { MAD_F(0x067141d5) /* 0.402650673 */, 17 }, + /* 3483 */ { MAD_F(0x0671e383) /* 0.402804864 */, 17 }, + /* 3484 */ { MAD_F(0x06728535) /* 0.402959070 */, 17 }, + /* 3485 */ { MAD_F(0x067326ec) /* 0.403113291 */, 17 }, + /* 3486 */ { MAD_F(0x0673c8a6) /* 0.403267526 */, 17 }, + /* 3487 */ { MAD_F(0x06746a64) /* 0.403421776 */, 17 }, + + /* 3488 */ { MAD_F(0x06750c26) /* 0.403576041 */, 17 }, + /* 3489 */ { MAD_F(0x0675adec) /* 0.403730320 */, 17 }, + /* 3490 */ { MAD_F(0x06764fb6) /* 0.403884615 */, 17 }, + /* 3491 */ { MAD_F(0x0676f184) /* 0.404038924 */, 17 }, + /* 3492 */ { MAD_F(0x06779356) /* 0.404193247 */, 17 }, + /* 3493 */ { MAD_F(0x0678352c) /* 0.404347586 */, 17 }, + /* 3494 */ { MAD_F(0x0678d706) /* 0.404501939 */, 17 }, + /* 3495 */ { MAD_F(0x067978e4) /* 0.404656307 */, 17 }, + /* 3496 */ { MAD_F(0x067a1ac6) /* 0.404810690 */, 17 }, + /* 3497 */ { MAD_F(0x067abcac) /* 0.404965087 */, 17 }, + /* 3498 */ { MAD_F(0x067b5e95) /* 0.405119499 */, 17 }, + /* 3499 */ { MAD_F(0x067c0083) /* 0.405273926 */, 17 }, + /* 3500 */ { MAD_F(0x067ca275) /* 0.405428368 */, 17 }, + /* 3501 */ { MAD_F(0x067d446a) /* 0.405582824 */, 17 }, + /* 3502 */ { MAD_F(0x067de664) /* 0.405737295 */, 17 }, + /* 3503 */ { MAD_F(0x067e8861) /* 0.405891781 */, 17 }, + + /* 3504 */ { MAD_F(0x067f2a62) /* 0.406046281 */, 17 }, + /* 3505 */ { MAD_F(0x067fcc68) /* 0.406200796 */, 17 }, + /* 3506 */ { MAD_F(0x06806e71) /* 0.406355326 */, 17 }, + /* 3507 */ { MAD_F(0x0681107e) /* 0.406509870 */, 17 }, + /* 3508 */ { MAD_F(0x0681b28f) /* 0.406664429 */, 17 }, + /* 3509 */ { MAD_F(0x068254a4) /* 0.406819003 */, 17 }, + /* 3510 */ { MAD_F(0x0682f6bd) /* 0.406973592 */, 17 }, + /* 3511 */ { MAD_F(0x068398da) /* 0.407128195 */, 17 }, + /* 3512 */ { MAD_F(0x06843afb) /* 0.407282813 */, 17 }, + /* 3513 */ { MAD_F(0x0684dd20) /* 0.407437445 */, 17 }, + /* 3514 */ { MAD_F(0x06857f49) /* 0.407592093 */, 17 }, + /* 3515 */ { MAD_F(0x06862176) /* 0.407746754 */, 17 }, + /* 3516 */ { MAD_F(0x0686c3a6) /* 0.407901431 */, 17 }, + /* 3517 */ { MAD_F(0x068765db) /* 0.408056122 */, 17 }, + /* 3518 */ { MAD_F(0x06880814) /* 0.408210828 */, 17 }, + /* 3519 */ { MAD_F(0x0688aa50) /* 0.408365549 */, 17 }, + + /* 3520 */ { MAD_F(0x06894c90) /* 0.408520284 */, 17 }, + /* 3521 */ { MAD_F(0x0689eed5) /* 0.408675034 */, 17 }, + /* 3522 */ { MAD_F(0x068a911d) /* 0.408829798 */, 17 }, + /* 3523 */ { MAD_F(0x068b3369) /* 0.408984577 */, 17 }, + /* 3524 */ { MAD_F(0x068bd5b9) /* 0.409139371 */, 17 }, + /* 3525 */ { MAD_F(0x068c780e) /* 0.409294180 */, 17 }, + /* 3526 */ { MAD_F(0x068d1a66) /* 0.409449003 */, 17 }, + /* 3527 */ { MAD_F(0x068dbcc1) /* 0.409603840 */, 17 }, + /* 3528 */ { MAD_F(0x068e5f21) /* 0.409758693 */, 17 }, + /* 3529 */ { MAD_F(0x068f0185) /* 0.409913560 */, 17 }, + /* 3530 */ { MAD_F(0x068fa3ed) /* 0.410068441 */, 17 }, + /* 3531 */ { MAD_F(0x06904658) /* 0.410223338 */, 17 }, + /* 3532 */ { MAD_F(0x0690e8c8) /* 0.410378249 */, 17 }, + /* 3533 */ { MAD_F(0x06918b3c) /* 0.410533174 */, 17 }, + /* 3534 */ { MAD_F(0x06922db3) /* 0.410688114 */, 17 }, + /* 3535 */ { MAD_F(0x0692d02e) /* 0.410843069 */, 17 }, + + /* 3536 */ { MAD_F(0x069372ae) /* 0.410998038 */, 17 }, + /* 3537 */ { MAD_F(0x06941531) /* 0.411153022 */, 17 }, + /* 3538 */ { MAD_F(0x0694b7b8) /* 0.411308021 */, 17 }, + /* 3539 */ { MAD_F(0x06955a43) /* 0.411463034 */, 17 }, + /* 3540 */ { MAD_F(0x0695fcd2) /* 0.411618062 */, 17 }, + /* 3541 */ { MAD_F(0x06969f65) /* 0.411773104 */, 17 }, + /* 3542 */ { MAD_F(0x069741fb) /* 0.411928161 */, 17 }, + /* 3543 */ { MAD_F(0x0697e496) /* 0.412083232 */, 17 }, + /* 3544 */ { MAD_F(0x06988735) /* 0.412238319 */, 17 }, + /* 3545 */ { MAD_F(0x069929d7) /* 0.412393419 */, 17 }, + /* 3546 */ { MAD_F(0x0699cc7e) /* 0.412548535 */, 17 }, + /* 3547 */ { MAD_F(0x069a6f28) /* 0.412703664 */, 17 }, + /* 3548 */ { MAD_F(0x069b11d6) /* 0.412858809 */, 17 }, + /* 3549 */ { MAD_F(0x069bb489) /* 0.413013968 */, 17 }, + /* 3550 */ { MAD_F(0x069c573f) /* 0.413169142 */, 17 }, + /* 3551 */ { MAD_F(0x069cf9f9) /* 0.413324330 */, 17 }, + + /* 3552 */ { MAD_F(0x069d9cb7) /* 0.413479532 */, 17 }, + /* 3553 */ { MAD_F(0x069e3f78) /* 0.413634750 */, 17 }, + /* 3554 */ { MAD_F(0x069ee23e) /* 0.413789982 */, 17 }, + /* 3555 */ { MAD_F(0x069f8508) /* 0.413945228 */, 17 }, + /* 3556 */ { MAD_F(0x06a027d5) /* 0.414100489 */, 17 }, + /* 3557 */ { MAD_F(0x06a0caa7) /* 0.414255765 */, 17 }, + /* 3558 */ { MAD_F(0x06a16d7c) /* 0.414411055 */, 17 }, + /* 3559 */ { MAD_F(0x06a21055) /* 0.414566359 */, 17 }, + /* 3560 */ { MAD_F(0x06a2b333) /* 0.414721679 */, 17 }, + /* 3561 */ { MAD_F(0x06a35614) /* 0.414877012 */, 17 }, + /* 3562 */ { MAD_F(0x06a3f8f9) /* 0.415032361 */, 17 }, + /* 3563 */ { MAD_F(0x06a49be2) /* 0.415187723 */, 17 }, + /* 3564 */ { MAD_F(0x06a53ece) /* 0.415343101 */, 17 }, + /* 3565 */ { MAD_F(0x06a5e1bf) /* 0.415498493 */, 17 }, + /* 3566 */ { MAD_F(0x06a684b4) /* 0.415653899 */, 17 }, + /* 3567 */ { MAD_F(0x06a727ac) /* 0.415809320 */, 17 }, + + /* 3568 */ { MAD_F(0x06a7caa9) /* 0.415964756 */, 17 }, + /* 3569 */ { MAD_F(0x06a86da9) /* 0.416120206 */, 17 }, + /* 3570 */ { MAD_F(0x06a910ad) /* 0.416275670 */, 17 }, + /* 3571 */ { MAD_F(0x06a9b3b5) /* 0.416431149 */, 17 }, + /* 3572 */ { MAD_F(0x06aa56c1) /* 0.416586643 */, 17 }, + /* 3573 */ { MAD_F(0x06aaf9d1) /* 0.416742151 */, 17 }, + /* 3574 */ { MAD_F(0x06ab9ce5) /* 0.416897673 */, 17 }, + /* 3575 */ { MAD_F(0x06ac3ffc) /* 0.417053210 */, 17 }, + /* 3576 */ { MAD_F(0x06ace318) /* 0.417208762 */, 17 }, + /* 3577 */ { MAD_F(0x06ad8637) /* 0.417364328 */, 17 }, + /* 3578 */ { MAD_F(0x06ae295b) /* 0.417519909 */, 17 }, + /* 3579 */ { MAD_F(0x06aecc82) /* 0.417675504 */, 17 }, + /* 3580 */ { MAD_F(0x06af6fad) /* 0.417831113 */, 17 }, + /* 3581 */ { MAD_F(0x06b012dc) /* 0.417986737 */, 17 }, + /* 3582 */ { MAD_F(0x06b0b60f) /* 0.418142376 */, 17 }, + /* 3583 */ { MAD_F(0x06b15946) /* 0.418298029 */, 17 }, + + /* 3584 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 17 }, + /* 3585 */ { MAD_F(0x06b29fbf) /* 0.418609378 */, 17 }, + /* 3586 */ { MAD_F(0x06b34302) /* 0.418765075 */, 17 }, + /* 3587 */ { MAD_F(0x06b3e648) /* 0.418920786 */, 17 }, + /* 3588 */ { MAD_F(0x06b48992) /* 0.419076511 */, 17 }, + /* 3589 */ { MAD_F(0x06b52ce0) /* 0.419232251 */, 17 }, + /* 3590 */ { MAD_F(0x06b5d032) /* 0.419388005 */, 17 }, + /* 3591 */ { MAD_F(0x06b67388) /* 0.419543774 */, 17 }, + /* 3592 */ { MAD_F(0x06b716e2) /* 0.419699557 */, 17 }, + /* 3593 */ { MAD_F(0x06b7ba3f) /* 0.419855355 */, 17 }, + /* 3594 */ { MAD_F(0x06b85da1) /* 0.420011167 */, 17 }, + /* 3595 */ { MAD_F(0x06b90106) /* 0.420166994 */, 17 }, + /* 3596 */ { MAD_F(0x06b9a470) /* 0.420322835 */, 17 }, + /* 3597 */ { MAD_F(0x06ba47dd) /* 0.420478690 */, 17 }, + /* 3598 */ { MAD_F(0x06baeb4e) /* 0.420634560 */, 17 }, + /* 3599 */ { MAD_F(0x06bb8ec3) /* 0.420790445 */, 17 }, + + /* 3600 */ { MAD_F(0x06bc323b) /* 0.420946343 */, 17 }, + /* 3601 */ { MAD_F(0x06bcd5b8) /* 0.421102257 */, 17 }, + /* 3602 */ { MAD_F(0x06bd7939) /* 0.421258184 */, 17 }, + /* 3603 */ { MAD_F(0x06be1cbd) /* 0.421414127 */, 17 }, + /* 3604 */ { MAD_F(0x06bec045) /* 0.421570083 */, 17 }, + /* 3605 */ { MAD_F(0x06bf63d1) /* 0.421726054 */, 17 }, + /* 3606 */ { MAD_F(0x06c00761) /* 0.421882040 */, 17 }, + /* 3607 */ { MAD_F(0x06c0aaf5) /* 0.422038039 */, 17 }, + /* 3608 */ { MAD_F(0x06c14e8d) /* 0.422194054 */, 17 }, + /* 3609 */ { MAD_F(0x06c1f229) /* 0.422350082 */, 17 }, + /* 3610 */ { MAD_F(0x06c295c8) /* 0.422506125 */, 17 }, + /* 3611 */ { MAD_F(0x06c3396c) /* 0.422662183 */, 17 }, + /* 3612 */ { MAD_F(0x06c3dd13) /* 0.422818255 */, 17 }, + /* 3613 */ { MAD_F(0x06c480be) /* 0.422974341 */, 17 }, + /* 3614 */ { MAD_F(0x06c5246d) /* 0.423130442 */, 17 }, + /* 3615 */ { MAD_F(0x06c5c820) /* 0.423286557 */, 17 }, + + /* 3616 */ { MAD_F(0x06c66bd6) /* 0.423442686 */, 17 }, + /* 3617 */ { MAD_F(0x06c70f91) /* 0.423598830 */, 17 }, + /* 3618 */ { MAD_F(0x06c7b34f) /* 0.423754988 */, 17 }, + /* 3619 */ { MAD_F(0x06c85712) /* 0.423911161 */, 17 }, + /* 3620 */ { MAD_F(0x06c8fad8) /* 0.424067348 */, 17 }, + /* 3621 */ { MAD_F(0x06c99ea2) /* 0.424223550 */, 17 }, + /* 3622 */ { MAD_F(0x06ca4270) /* 0.424379765 */, 17 }, + /* 3623 */ { MAD_F(0x06cae641) /* 0.424535996 */, 17 }, + /* 3624 */ { MAD_F(0x06cb8a17) /* 0.424692240 */, 17 }, + /* 3625 */ { MAD_F(0x06cc2df0) /* 0.424848499 */, 17 }, + /* 3626 */ { MAD_F(0x06ccd1ce) /* 0.425004772 */, 17 }, + /* 3627 */ { MAD_F(0x06cd75af) /* 0.425161060 */, 17 }, + /* 3628 */ { MAD_F(0x06ce1994) /* 0.425317362 */, 17 }, + /* 3629 */ { MAD_F(0x06cebd7d) /* 0.425473678 */, 17 }, + /* 3630 */ { MAD_F(0x06cf6169) /* 0.425630009 */, 17 }, + /* 3631 */ { MAD_F(0x06d0055a) /* 0.425786354 */, 17 }, + + /* 3632 */ { MAD_F(0x06d0a94e) /* 0.425942714 */, 17 }, + /* 3633 */ { MAD_F(0x06d14d47) /* 0.426099088 */, 17 }, + /* 3634 */ { MAD_F(0x06d1f143) /* 0.426255476 */, 17 }, + /* 3635 */ { MAD_F(0x06d29543) /* 0.426411878 */, 17 }, + /* 3636 */ { MAD_F(0x06d33947) /* 0.426568295 */, 17 }, + /* 3637 */ { MAD_F(0x06d3dd4e) /* 0.426724726 */, 17 }, + /* 3638 */ { MAD_F(0x06d4815a) /* 0.426881172 */, 17 }, + /* 3639 */ { MAD_F(0x06d52569) /* 0.427037632 */, 17 }, + /* 3640 */ { MAD_F(0x06d5c97c) /* 0.427194106 */, 17 }, + /* 3641 */ { MAD_F(0x06d66d93) /* 0.427350594 */, 17 }, + /* 3642 */ { MAD_F(0x06d711ae) /* 0.427507097 */, 17 }, + /* 3643 */ { MAD_F(0x06d7b5cd) /* 0.427663614 */, 17 }, + /* 3644 */ { MAD_F(0x06d859f0) /* 0.427820146 */, 17 }, + /* 3645 */ { MAD_F(0x06d8fe16) /* 0.427976692 */, 17 }, + /* 3646 */ { MAD_F(0x06d9a240) /* 0.428133252 */, 17 }, + /* 3647 */ { MAD_F(0x06da466f) /* 0.428289826 */, 17 }, + + /* 3648 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 17 }, + /* 3649 */ { MAD_F(0x06db8ed6) /* 0.428603018 */, 17 }, + /* 3650 */ { MAD_F(0x06dc3310) /* 0.428759635 */, 17 }, + /* 3651 */ { MAD_F(0x06dcd74d) /* 0.428916267 */, 17 }, + /* 3652 */ { MAD_F(0x06dd7b8f) /* 0.429072913 */, 17 }, + /* 3653 */ { MAD_F(0x06de1fd4) /* 0.429229573 */, 17 }, + /* 3654 */ { MAD_F(0x06dec41d) /* 0.429386248 */, 17 }, + /* 3655 */ { MAD_F(0x06df686a) /* 0.429542937 */, 17 }, + /* 3656 */ { MAD_F(0x06e00cbb) /* 0.429699640 */, 17 }, + /* 3657 */ { MAD_F(0x06e0b10f) /* 0.429856357 */, 17 }, + /* 3658 */ { MAD_F(0x06e15567) /* 0.430013089 */, 17 }, + /* 3659 */ { MAD_F(0x06e1f9c4) /* 0.430169835 */, 17 }, + /* 3660 */ { MAD_F(0x06e29e24) /* 0.430326595 */, 17 }, + /* 3661 */ { MAD_F(0x06e34287) /* 0.430483370 */, 17 }, + /* 3662 */ { MAD_F(0x06e3e6ef) /* 0.430640159 */, 17 }, + /* 3663 */ { MAD_F(0x06e48b5b) /* 0.430796962 */, 17 }, + + /* 3664 */ { MAD_F(0x06e52fca) /* 0.430953779 */, 17 }, + /* 3665 */ { MAD_F(0x06e5d43d) /* 0.431110611 */, 17 }, + /* 3666 */ { MAD_F(0x06e678b4) /* 0.431267457 */, 17 }, + /* 3667 */ { MAD_F(0x06e71d2f) /* 0.431424317 */, 17 }, + /* 3668 */ { MAD_F(0x06e7c1ae) /* 0.431581192 */, 17 }, + /* 3669 */ { MAD_F(0x06e86630) /* 0.431738080 */, 17 }, + /* 3670 */ { MAD_F(0x06e90ab7) /* 0.431894983 */, 17 }, + /* 3671 */ { MAD_F(0x06e9af41) /* 0.432051900 */, 17 }, + /* 3672 */ { MAD_F(0x06ea53cf) /* 0.432208832 */, 17 }, + /* 3673 */ { MAD_F(0x06eaf860) /* 0.432365778 */, 17 }, + /* 3674 */ { MAD_F(0x06eb9cf6) /* 0.432522737 */, 17 }, + /* 3675 */ { MAD_F(0x06ec418f) /* 0.432679712 */, 17 }, + /* 3676 */ { MAD_F(0x06ece62d) /* 0.432836700 */, 17 }, + /* 3677 */ { MAD_F(0x06ed8ace) /* 0.432993703 */, 17 }, + /* 3678 */ { MAD_F(0x06ee2f73) /* 0.433150720 */, 17 }, + /* 3679 */ { MAD_F(0x06eed41b) /* 0.433307751 */, 17 }, + + /* 3680 */ { MAD_F(0x06ef78c8) /* 0.433464796 */, 17 }, + /* 3681 */ { MAD_F(0x06f01d78) /* 0.433621856 */, 17 }, + /* 3682 */ { MAD_F(0x06f0c22c) /* 0.433778929 */, 17 }, + /* 3683 */ { MAD_F(0x06f166e4) /* 0.433936017 */, 17 }, + /* 3684 */ { MAD_F(0x06f20ba0) /* 0.434093120 */, 17 }, + /* 3685 */ { MAD_F(0x06f2b060) /* 0.434250236 */, 17 }, + /* 3686 */ { MAD_F(0x06f35523) /* 0.434407367 */, 17 }, + /* 3687 */ { MAD_F(0x06f3f9eb) /* 0.434564512 */, 17 }, + /* 3688 */ { MAD_F(0x06f49eb6) /* 0.434721671 */, 17 }, + /* 3689 */ { MAD_F(0x06f54385) /* 0.434878844 */, 17 }, + /* 3690 */ { MAD_F(0x06f5e857) /* 0.435036032 */, 17 }, + /* 3691 */ { MAD_F(0x06f68d2e) /* 0.435193233 */, 17 }, + /* 3692 */ { MAD_F(0x06f73208) /* 0.435350449 */, 17 }, + /* 3693 */ { MAD_F(0x06f7d6e6) /* 0.435507679 */, 17 }, + /* 3694 */ { MAD_F(0x06f87bc8) /* 0.435664924 */, 17 }, + /* 3695 */ { MAD_F(0x06f920ae) /* 0.435822182 */, 17 }, + + /* 3696 */ { MAD_F(0x06f9c597) /* 0.435979455 */, 17 }, + /* 3697 */ { MAD_F(0x06fa6a85) /* 0.436136741 */, 17 }, + /* 3698 */ { MAD_F(0x06fb0f76) /* 0.436294042 */, 17 }, + /* 3699 */ { MAD_F(0x06fbb46b) /* 0.436451358 */, 17 }, + /* 3700 */ { MAD_F(0x06fc5964) /* 0.436608687 */, 17 }, + /* 3701 */ { MAD_F(0x06fcfe60) /* 0.436766031 */, 17 }, + /* 3702 */ { MAD_F(0x06fda361) /* 0.436923388 */, 17 }, + /* 3703 */ { MAD_F(0x06fe4865) /* 0.437080760 */, 17 }, + /* 3704 */ { MAD_F(0x06feed6d) /* 0.437238146 */, 17 }, + /* 3705 */ { MAD_F(0x06ff9279) /* 0.437395547 */, 17 }, + /* 3706 */ { MAD_F(0x07003788) /* 0.437552961 */, 17 }, + /* 3707 */ { MAD_F(0x0700dc9c) /* 0.437710389 */, 17 }, + /* 3708 */ { MAD_F(0x070181b3) /* 0.437867832 */, 17 }, + /* 3709 */ { MAD_F(0x070226ce) /* 0.438025289 */, 17 }, + /* 3710 */ { MAD_F(0x0702cbed) /* 0.438182760 */, 17 }, + /* 3711 */ { MAD_F(0x0703710f) /* 0.438340245 */, 17 }, + + /* 3712 */ { MAD_F(0x07041636) /* 0.438497744 */, 17 }, + /* 3713 */ { MAD_F(0x0704bb60) /* 0.438655258 */, 17 }, + /* 3714 */ { MAD_F(0x0705608e) /* 0.438812785 */, 17 }, + /* 3715 */ { MAD_F(0x070605c0) /* 0.438970327 */, 17 }, + /* 3716 */ { MAD_F(0x0706aaf5) /* 0.439127883 */, 17 }, + /* 3717 */ { MAD_F(0x0707502f) /* 0.439285453 */, 17 }, + /* 3718 */ { MAD_F(0x0707f56c) /* 0.439443037 */, 17 }, + /* 3719 */ { MAD_F(0x07089aad) /* 0.439600635 */, 17 }, + /* 3720 */ { MAD_F(0x07093ff2) /* 0.439758248 */, 17 }, + /* 3721 */ { MAD_F(0x0709e53a) /* 0.439915874 */, 17 }, + /* 3722 */ { MAD_F(0x070a8a86) /* 0.440073515 */, 17 }, + /* 3723 */ { MAD_F(0x070b2fd7) /* 0.440231170 */, 17 }, + /* 3724 */ { MAD_F(0x070bd52a) /* 0.440388839 */, 17 }, + /* 3725 */ { MAD_F(0x070c7a82) /* 0.440546522 */, 17 }, + /* 3726 */ { MAD_F(0x070d1fde) /* 0.440704219 */, 17 }, + /* 3727 */ { MAD_F(0x070dc53d) /* 0.440861930 */, 17 }, + + /* 3728 */ { MAD_F(0x070e6aa0) /* 0.441019655 */, 17 }, + /* 3729 */ { MAD_F(0x070f1007) /* 0.441177395 */, 17 }, + /* 3730 */ { MAD_F(0x070fb571) /* 0.441335148 */, 17 }, + /* 3731 */ { MAD_F(0x07105ae0) /* 0.441492916 */, 17 }, + /* 3732 */ { MAD_F(0x07110052) /* 0.441650697 */, 17 }, + /* 3733 */ { MAD_F(0x0711a5c8) /* 0.441808493 */, 17 }, + /* 3734 */ { MAD_F(0x07124b42) /* 0.441966303 */, 17 }, + /* 3735 */ { MAD_F(0x0712f0bf) /* 0.442124127 */, 17 }, + /* 3736 */ { MAD_F(0x07139641) /* 0.442281965 */, 17 }, + /* 3737 */ { MAD_F(0x07143bc6) /* 0.442439817 */, 17 }, + /* 3738 */ { MAD_F(0x0714e14f) /* 0.442597683 */, 17 }, + /* 3739 */ { MAD_F(0x071586db) /* 0.442755564 */, 17 }, + /* 3740 */ { MAD_F(0x07162c6c) /* 0.442913458 */, 17 }, + /* 3741 */ { MAD_F(0x0716d200) /* 0.443071366 */, 17 }, + /* 3742 */ { MAD_F(0x07177798) /* 0.443229289 */, 17 }, + /* 3743 */ { MAD_F(0x07181d34) /* 0.443387226 */, 17 }, + + /* 3744 */ { MAD_F(0x0718c2d3) /* 0.443545176 */, 17 }, + /* 3745 */ { MAD_F(0x07196877) /* 0.443703141 */, 17 }, + /* 3746 */ { MAD_F(0x071a0e1e) /* 0.443861120 */, 17 }, + /* 3747 */ { MAD_F(0x071ab3c9) /* 0.444019113 */, 17 }, + /* 3748 */ { MAD_F(0x071b5977) /* 0.444177119 */, 17 }, + /* 3749 */ { MAD_F(0x071bff2a) /* 0.444335140 */, 17 }, + /* 3750 */ { MAD_F(0x071ca4e0) /* 0.444493175 */, 17 }, + /* 3751 */ { MAD_F(0x071d4a9a) /* 0.444651224 */, 17 }, + /* 3752 */ { MAD_F(0x071df058) /* 0.444809288 */, 17 }, + /* 3753 */ { MAD_F(0x071e9619) /* 0.444967365 */, 17 }, + /* 3754 */ { MAD_F(0x071f3bde) /* 0.445125456 */, 17 }, + /* 3755 */ { MAD_F(0x071fe1a8) /* 0.445283561 */, 17 }, + /* 3756 */ { MAD_F(0x07208774) /* 0.445441680 */, 17 }, + /* 3757 */ { MAD_F(0x07212d45) /* 0.445599814 */, 17 }, + /* 3758 */ { MAD_F(0x0721d319) /* 0.445757961 */, 17 }, + /* 3759 */ { MAD_F(0x072278f1) /* 0.445916122 */, 17 }, + + /* 3760 */ { MAD_F(0x07231ecd) /* 0.446074298 */, 17 }, + /* 3761 */ { MAD_F(0x0723c4ad) /* 0.446232487 */, 17 }, + /* 3762 */ { MAD_F(0x07246a90) /* 0.446390690 */, 17 }, + /* 3763 */ { MAD_F(0x07251077) /* 0.446548908 */, 17 }, + /* 3764 */ { MAD_F(0x0725b662) /* 0.446707139 */, 17 }, + /* 3765 */ { MAD_F(0x07265c51) /* 0.446865385 */, 17 }, + /* 3766 */ { MAD_F(0x07270244) /* 0.447023644 */, 17 }, + /* 3767 */ { MAD_F(0x0727a83a) /* 0.447181918 */, 17 }, + /* 3768 */ { MAD_F(0x07284e34) /* 0.447340205 */, 17 }, + /* 3769 */ { MAD_F(0x0728f431) /* 0.447498507 */, 17 }, + /* 3770 */ { MAD_F(0x07299a33) /* 0.447656822 */, 17 }, + /* 3771 */ { MAD_F(0x072a4038) /* 0.447815152 */, 17 }, + /* 3772 */ { MAD_F(0x072ae641) /* 0.447973495 */, 17 }, + /* 3773 */ { MAD_F(0x072b8c4e) /* 0.448131853 */, 17 }, + /* 3774 */ { MAD_F(0x072c325e) /* 0.448290224 */, 17 }, + /* 3775 */ { MAD_F(0x072cd873) /* 0.448448609 */, 17 }, + + /* 3776 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 17 }, + /* 3777 */ { MAD_F(0x072e24a7) /* 0.448765422 */, 17 }, + /* 3778 */ { MAD_F(0x072ecac6) /* 0.448923850 */, 17 }, + /* 3779 */ { MAD_F(0x072f70e9) /* 0.449082291 */, 17 }, + /* 3780 */ { MAD_F(0x07301710) /* 0.449240746 */, 17 }, + /* 3781 */ { MAD_F(0x0730bd3b) /* 0.449399216 */, 17 }, + /* 3782 */ { MAD_F(0x0731636a) /* 0.449557699 */, 17 }, + /* 3783 */ { MAD_F(0x0732099c) /* 0.449716196 */, 17 }, + /* 3784 */ { MAD_F(0x0732afd2) /* 0.449874708 */, 17 }, + /* 3785 */ { MAD_F(0x0733560c) /* 0.450033233 */, 17 }, + /* 3786 */ { MAD_F(0x0733fc49) /* 0.450191772 */, 17 }, + /* 3787 */ { MAD_F(0x0734a28b) /* 0.450350325 */, 17 }, + /* 3788 */ { MAD_F(0x073548d0) /* 0.450508892 */, 17 }, + /* 3789 */ { MAD_F(0x0735ef18) /* 0.450667473 */, 17 }, + /* 3790 */ { MAD_F(0x07369565) /* 0.450826068 */, 17 }, + /* 3791 */ { MAD_F(0x07373bb5) /* 0.450984677 */, 17 }, + + /* 3792 */ { MAD_F(0x0737e209) /* 0.451143300 */, 17 }, + /* 3793 */ { MAD_F(0x07388861) /* 0.451301937 */, 17 }, + /* 3794 */ { MAD_F(0x07392ebc) /* 0.451460588 */, 17 }, + /* 3795 */ { MAD_F(0x0739d51c) /* 0.451619252 */, 17 }, + /* 3796 */ { MAD_F(0x073a7b7f) /* 0.451777931 */, 17 }, + /* 3797 */ { MAD_F(0x073b21e5) /* 0.451936623 */, 17 }, + /* 3798 */ { MAD_F(0x073bc850) /* 0.452095330 */, 17 }, + /* 3799 */ { MAD_F(0x073c6ebe) /* 0.452254050 */, 17 }, + /* 3800 */ { MAD_F(0x073d1530) /* 0.452412785 */, 17 }, + /* 3801 */ { MAD_F(0x073dbba6) /* 0.452571533 */, 17 }, + /* 3802 */ { MAD_F(0x073e621f) /* 0.452730295 */, 17 }, + /* 3803 */ { MAD_F(0x073f089c) /* 0.452889071 */, 17 }, + /* 3804 */ { MAD_F(0x073faf1d) /* 0.453047861 */, 17 }, + /* 3805 */ { MAD_F(0x074055a2) /* 0.453206665 */, 17 }, + /* 3806 */ { MAD_F(0x0740fc2a) /* 0.453365483 */, 17 }, + /* 3807 */ { MAD_F(0x0741a2b6) /* 0.453524315 */, 17 }, + + /* 3808 */ { MAD_F(0x07424946) /* 0.453683161 */, 17 }, + /* 3809 */ { MAD_F(0x0742efd9) /* 0.453842020 */, 17 }, + /* 3810 */ { MAD_F(0x07439671) /* 0.454000894 */, 17 }, + /* 3811 */ { MAD_F(0x07443d0c) /* 0.454159781 */, 17 }, + /* 3812 */ { MAD_F(0x0744e3aa) /* 0.454318683 */, 17 }, + /* 3813 */ { MAD_F(0x07458a4d) /* 0.454477598 */, 17 }, + /* 3814 */ { MAD_F(0x074630f3) /* 0.454636527 */, 17 }, + /* 3815 */ { MAD_F(0x0746d79d) /* 0.454795470 */, 17 }, + /* 3816 */ { MAD_F(0x07477e4b) /* 0.454954427 */, 17 }, + /* 3817 */ { MAD_F(0x074824fc) /* 0.455113397 */, 17 }, + /* 3818 */ { MAD_F(0x0748cbb1) /* 0.455272382 */, 17 }, + /* 3819 */ { MAD_F(0x0749726a) /* 0.455431381 */, 17 }, + /* 3820 */ { MAD_F(0x074a1927) /* 0.455590393 */, 17 }, + /* 3821 */ { MAD_F(0x074abfe7) /* 0.455749419 */, 17 }, + /* 3822 */ { MAD_F(0x074b66ab) /* 0.455908459 */, 17 }, + /* 3823 */ { MAD_F(0x074c0d73) /* 0.456067513 */, 17 }, + + /* 3824 */ { MAD_F(0x074cb43e) /* 0.456226581 */, 17 }, + /* 3825 */ { MAD_F(0x074d5b0d) /* 0.456385663 */, 17 }, + /* 3826 */ { MAD_F(0x074e01e0) /* 0.456544759 */, 17 }, + /* 3827 */ { MAD_F(0x074ea8b7) /* 0.456703868 */, 17 }, + /* 3828 */ { MAD_F(0x074f4f91) /* 0.456862992 */, 17 }, + /* 3829 */ { MAD_F(0x074ff66f) /* 0.457022129 */, 17 }, + /* 3830 */ { MAD_F(0x07509d51) /* 0.457181280 */, 17 }, + /* 3831 */ { MAD_F(0x07514437) /* 0.457340445 */, 17 }, + /* 3832 */ { MAD_F(0x0751eb20) /* 0.457499623 */, 17 }, + /* 3833 */ { MAD_F(0x0752920d) /* 0.457658816 */, 17 }, + /* 3834 */ { MAD_F(0x075338fd) /* 0.457818022 */, 17 }, + /* 3835 */ { MAD_F(0x0753dff2) /* 0.457977243 */, 17 }, + /* 3836 */ { MAD_F(0x075486ea) /* 0.458136477 */, 17 }, + /* 3837 */ { MAD_F(0x07552de6) /* 0.458295725 */, 17 }, + /* 3838 */ { MAD_F(0x0755d4e5) /* 0.458454987 */, 17 }, + /* 3839 */ { MAD_F(0x07567be8) /* 0.458614262 */, 17 }, + + /* 3840 */ { MAD_F(0x075722ef) /* 0.458773552 */, 17 }, + /* 3841 */ { MAD_F(0x0757c9fa) /* 0.458932855 */, 17 }, + /* 3842 */ { MAD_F(0x07587108) /* 0.459092172 */, 17 }, + /* 3843 */ { MAD_F(0x0759181a) /* 0.459251503 */, 17 }, + /* 3844 */ { MAD_F(0x0759bf30) /* 0.459410848 */, 17 }, + /* 3845 */ { MAD_F(0x075a664a) /* 0.459570206 */, 17 }, + /* 3846 */ { MAD_F(0x075b0d67) /* 0.459729579 */, 17 }, + /* 3847 */ { MAD_F(0x075bb488) /* 0.459888965 */, 17 }, + /* 3848 */ { MAD_F(0x075c5bac) /* 0.460048365 */, 17 }, + /* 3849 */ { MAD_F(0x075d02d5) /* 0.460207779 */, 17 }, + /* 3850 */ { MAD_F(0x075daa01) /* 0.460367206 */, 17 }, + /* 3851 */ { MAD_F(0x075e5130) /* 0.460526648 */, 17 }, + /* 3852 */ { MAD_F(0x075ef864) /* 0.460686103 */, 17 }, + /* 3853 */ { MAD_F(0x075f9f9b) /* 0.460845572 */, 17 }, + /* 3854 */ { MAD_F(0x076046d6) /* 0.461005055 */, 17 }, + /* 3855 */ { MAD_F(0x0760ee14) /* 0.461164552 */, 17 }, + + /* 3856 */ { MAD_F(0x07619557) /* 0.461324062 */, 17 }, + /* 3857 */ { MAD_F(0x07623c9d) /* 0.461483586 */, 17 }, + /* 3858 */ { MAD_F(0x0762e3e6) /* 0.461643124 */, 17 }, + /* 3859 */ { MAD_F(0x07638b34) /* 0.461802676 */, 17 }, + /* 3860 */ { MAD_F(0x07643285) /* 0.461962242 */, 17 }, + /* 3861 */ { MAD_F(0x0764d9d9) /* 0.462121821 */, 17 }, + /* 3862 */ { MAD_F(0x07658132) /* 0.462281414 */, 17 }, + /* 3863 */ { MAD_F(0x0766288e) /* 0.462441021 */, 17 }, + /* 3864 */ { MAD_F(0x0766cfee) /* 0.462600642 */, 17 }, + /* 3865 */ { MAD_F(0x07677751) /* 0.462760276 */, 17 }, + /* 3866 */ { MAD_F(0x07681eb9) /* 0.462919924 */, 17 }, + /* 3867 */ { MAD_F(0x0768c624) /* 0.463079586 */, 17 }, + /* 3868 */ { MAD_F(0x07696d92) /* 0.463239262 */, 17 }, + /* 3869 */ { MAD_F(0x076a1505) /* 0.463398951 */, 17 }, + /* 3870 */ { MAD_F(0x076abc7b) /* 0.463558655 */, 17 }, + /* 3871 */ { MAD_F(0x076b63f4) /* 0.463718372 */, 17 }, + + /* 3872 */ { MAD_F(0x076c0b72) /* 0.463878102 */, 17 }, + /* 3873 */ { MAD_F(0x076cb2f3) /* 0.464037847 */, 17 }, + /* 3874 */ { MAD_F(0x076d5a78) /* 0.464197605 */, 17 }, + /* 3875 */ { MAD_F(0x076e0200) /* 0.464357377 */, 17 }, + /* 3876 */ { MAD_F(0x076ea98c) /* 0.464517163 */, 17 }, + /* 3877 */ { MAD_F(0x076f511c) /* 0.464676962 */, 17 }, + /* 3878 */ { MAD_F(0x076ff8b0) /* 0.464836776 */, 17 }, + /* 3879 */ { MAD_F(0x0770a047) /* 0.464996603 */, 17 }, + /* 3880 */ { MAD_F(0x077147e2) /* 0.465156443 */, 17 }, + /* 3881 */ { MAD_F(0x0771ef80) /* 0.465316298 */, 17 }, + /* 3882 */ { MAD_F(0x07729723) /* 0.465476166 */, 17 }, + /* 3883 */ { MAD_F(0x07733ec9) /* 0.465636048 */, 17 }, + /* 3884 */ { MAD_F(0x0773e672) /* 0.465795943 */, 17 }, + /* 3885 */ { MAD_F(0x07748e20) /* 0.465955853 */, 17 }, + /* 3886 */ { MAD_F(0x077535d1) /* 0.466115776 */, 17 }, + /* 3887 */ { MAD_F(0x0775dd85) /* 0.466275713 */, 17 }, + + /* 3888 */ { MAD_F(0x0776853e) /* 0.466435663 */, 17 }, + /* 3889 */ { MAD_F(0x07772cfa) /* 0.466595627 */, 17 }, + /* 3890 */ { MAD_F(0x0777d4ba) /* 0.466755605 */, 17 }, + /* 3891 */ { MAD_F(0x07787c7d) /* 0.466915597 */, 17 }, + /* 3892 */ { MAD_F(0x07792444) /* 0.467075602 */, 17 }, + /* 3893 */ { MAD_F(0x0779cc0f) /* 0.467235621 */, 17 }, + /* 3894 */ { MAD_F(0x077a73dd) /* 0.467395654 */, 17 }, + /* 3895 */ { MAD_F(0x077b1baf) /* 0.467555701 */, 17 }, + /* 3896 */ { MAD_F(0x077bc385) /* 0.467715761 */, 17 }, + /* 3897 */ { MAD_F(0x077c6b5f) /* 0.467875835 */, 17 }, + /* 3898 */ { MAD_F(0x077d133c) /* 0.468035922 */, 17 }, + /* 3899 */ { MAD_F(0x077dbb1d) /* 0.468196023 */, 17 }, + /* 3900 */ { MAD_F(0x077e6301) /* 0.468356138 */, 17 }, + /* 3901 */ { MAD_F(0x077f0ae9) /* 0.468516267 */, 17 }, + /* 3902 */ { MAD_F(0x077fb2d5) /* 0.468676409 */, 17 }, + /* 3903 */ { MAD_F(0x07805ac5) /* 0.468836565 */, 17 }, + + /* 3904 */ { MAD_F(0x078102b8) /* 0.468996735 */, 17 }, + /* 3905 */ { MAD_F(0x0781aaaf) /* 0.469156918 */, 17 }, + /* 3906 */ { MAD_F(0x078252aa) /* 0.469317115 */, 17 }, + /* 3907 */ { MAD_F(0x0782faa8) /* 0.469477326 */, 17 }, + /* 3908 */ { MAD_F(0x0783a2aa) /* 0.469637550 */, 17 }, + /* 3909 */ { MAD_F(0x07844aaf) /* 0.469797788 */, 17 }, + /* 3910 */ { MAD_F(0x0784f2b8) /* 0.469958040 */, 17 }, + /* 3911 */ { MAD_F(0x07859ac5) /* 0.470118305 */, 17 }, + /* 3912 */ { MAD_F(0x078642d6) /* 0.470278584 */, 17 }, + /* 3913 */ { MAD_F(0x0786eaea) /* 0.470438877 */, 17 }, + /* 3914 */ { MAD_F(0x07879302) /* 0.470599183 */, 17 }, + /* 3915 */ { MAD_F(0x07883b1e) /* 0.470759503 */, 17 }, + /* 3916 */ { MAD_F(0x0788e33d) /* 0.470919836 */, 17 }, + /* 3917 */ { MAD_F(0x07898b60) /* 0.471080184 */, 17 }, + /* 3918 */ { MAD_F(0x078a3386) /* 0.471240545 */, 17 }, + /* 3919 */ { MAD_F(0x078adbb0) /* 0.471400919 */, 17 }, + + /* 3920 */ { MAD_F(0x078b83de) /* 0.471561307 */, 17 }, + /* 3921 */ { MAD_F(0x078c2c10) /* 0.471721709 */, 17 }, + /* 3922 */ { MAD_F(0x078cd445) /* 0.471882125 */, 17 }, + /* 3923 */ { MAD_F(0x078d7c7e) /* 0.472042554 */, 17 }, + /* 3924 */ { MAD_F(0x078e24ba) /* 0.472202996 */, 17 }, + /* 3925 */ { MAD_F(0x078eccfb) /* 0.472363453 */, 17 }, + /* 3926 */ { MAD_F(0x078f753e) /* 0.472523923 */, 17 }, + /* 3927 */ { MAD_F(0x07901d86) /* 0.472684406 */, 17 }, + /* 3928 */ { MAD_F(0x0790c5d1) /* 0.472844904 */, 17 }, + /* 3929 */ { MAD_F(0x07916e20) /* 0.473005414 */, 17 }, + /* 3930 */ { MAD_F(0x07921672) /* 0.473165939 */, 17 }, + /* 3931 */ { MAD_F(0x0792bec8) /* 0.473326477 */, 17 }, + /* 3932 */ { MAD_F(0x07936722) /* 0.473487029 */, 17 }, + /* 3933 */ { MAD_F(0x07940f80) /* 0.473647594 */, 17 }, + /* 3934 */ { MAD_F(0x0794b7e1) /* 0.473808173 */, 17 }, + /* 3935 */ { MAD_F(0x07956045) /* 0.473968765 */, 17 }, + + /* 3936 */ { MAD_F(0x079608ae) /* 0.474129372 */, 17 }, + /* 3937 */ { MAD_F(0x0796b11a) /* 0.474289991 */, 17 }, + /* 3938 */ { MAD_F(0x0797598a) /* 0.474450625 */, 17 }, + /* 3939 */ { MAD_F(0x079801fd) /* 0.474611272 */, 17 }, + /* 3940 */ { MAD_F(0x0798aa74) /* 0.474771932 */, 17 }, + /* 3941 */ { MAD_F(0x079952ee) /* 0.474932606 */, 17 }, + /* 3942 */ { MAD_F(0x0799fb6d) /* 0.475093294 */, 17 }, + /* 3943 */ { MAD_F(0x079aa3ef) /* 0.475253995 */, 17 }, + /* 3944 */ { MAD_F(0x079b4c74) /* 0.475414710 */, 17 }, + /* 3945 */ { MAD_F(0x079bf4fd) /* 0.475575439 */, 17 }, + /* 3946 */ { MAD_F(0x079c9d8a) /* 0.475736181 */, 17 }, + /* 3947 */ { MAD_F(0x079d461b) /* 0.475896936 */, 17 }, + /* 3948 */ { MAD_F(0x079deeaf) /* 0.476057705 */, 17 }, + /* 3949 */ { MAD_F(0x079e9747) /* 0.476218488 */, 17 }, + /* 3950 */ { MAD_F(0x079f3fe2) /* 0.476379285 */, 17 }, + /* 3951 */ { MAD_F(0x079fe881) /* 0.476540095 */, 17 }, + + /* 3952 */ { MAD_F(0x07a09124) /* 0.476700918 */, 17 }, + /* 3953 */ { MAD_F(0x07a139ca) /* 0.476861755 */, 17 }, + /* 3954 */ { MAD_F(0x07a1e274) /* 0.477022606 */, 17 }, + /* 3955 */ { MAD_F(0x07a28b22) /* 0.477183470 */, 17 }, + /* 3956 */ { MAD_F(0x07a333d3) /* 0.477344348 */, 17 }, + /* 3957 */ { MAD_F(0x07a3dc88) /* 0.477505239 */, 17 }, + /* 3958 */ { MAD_F(0x07a48541) /* 0.477666144 */, 17 }, + /* 3959 */ { MAD_F(0x07a52dfd) /* 0.477827062 */, 17 }, + /* 3960 */ { MAD_F(0x07a5d6bd) /* 0.477987994 */, 17 }, + /* 3961 */ { MAD_F(0x07a67f80) /* 0.478148940 */, 17 }, + /* 3962 */ { MAD_F(0x07a72847) /* 0.478309899 */, 17 }, + /* 3963 */ { MAD_F(0x07a7d112) /* 0.478470871 */, 17 }, + /* 3964 */ { MAD_F(0x07a879e1) /* 0.478631857 */, 17 }, + /* 3965 */ { MAD_F(0x07a922b3) /* 0.478792857 */, 17 }, + /* 3966 */ { MAD_F(0x07a9cb88) /* 0.478953870 */, 17 }, + /* 3967 */ { MAD_F(0x07aa7462) /* 0.479114897 */, 17 }, + + /* 3968 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 17 }, + /* 3969 */ { MAD_F(0x07abc61f) /* 0.479436991 */, 17 }, + /* 3970 */ { MAD_F(0x07ac6f03) /* 0.479598058 */, 17 }, + /* 3971 */ { MAD_F(0x07ad17eb) /* 0.479759139 */, 17 }, + /* 3972 */ { MAD_F(0x07adc0d6) /* 0.479920233 */, 17 }, + /* 3973 */ { MAD_F(0x07ae69c6) /* 0.480081341 */, 17 }, + /* 3974 */ { MAD_F(0x07af12b8) /* 0.480242463 */, 17 }, + /* 3975 */ { MAD_F(0x07afbbaf) /* 0.480403598 */, 17 }, + /* 3976 */ { MAD_F(0x07b064a8) /* 0.480564746 */, 17 }, + /* 3977 */ { MAD_F(0x07b10da6) /* 0.480725908 */, 17 }, + /* 3978 */ { MAD_F(0x07b1b6a7) /* 0.480887083 */, 17 }, + /* 3979 */ { MAD_F(0x07b25fac) /* 0.481048272 */, 17 }, + /* 3980 */ { MAD_F(0x07b308b5) /* 0.481209475 */, 17 }, + /* 3981 */ { MAD_F(0x07b3b1c1) /* 0.481370691 */, 17 }, + /* 3982 */ { MAD_F(0x07b45ad0) /* 0.481531920 */, 17 }, + /* 3983 */ { MAD_F(0x07b503e4) /* 0.481693163 */, 17 }, + + /* 3984 */ { MAD_F(0x07b5acfb) /* 0.481854420 */, 17 }, + /* 3985 */ { MAD_F(0x07b65615) /* 0.482015690 */, 17 }, + /* 3986 */ { MAD_F(0x07b6ff33) /* 0.482176973 */, 17 }, + /* 3987 */ { MAD_F(0x07b7a855) /* 0.482338270 */, 17 }, + /* 3988 */ { MAD_F(0x07b8517b) /* 0.482499580 */, 17 }, + /* 3989 */ { MAD_F(0x07b8faa4) /* 0.482660904 */, 17 }, + /* 3990 */ { MAD_F(0x07b9a3d0) /* 0.482822242 */, 17 }, + /* 3991 */ { MAD_F(0x07ba4d01) /* 0.482983592 */, 17 }, + /* 3992 */ { MAD_F(0x07baf635) /* 0.483144957 */, 17 }, + /* 3993 */ { MAD_F(0x07bb9f6c) /* 0.483306335 */, 17 }, + /* 3994 */ { MAD_F(0x07bc48a7) /* 0.483467726 */, 17 }, + /* 3995 */ { MAD_F(0x07bcf1e6) /* 0.483629131 */, 17 }, + /* 3996 */ { MAD_F(0x07bd9b28) /* 0.483790549 */, 17 }, + /* 3997 */ { MAD_F(0x07be446e) /* 0.483951980 */, 17 }, + /* 3998 */ { MAD_F(0x07beedb8) /* 0.484113426 */, 17 }, + /* 3999 */ { MAD_F(0x07bf9705) /* 0.484274884 */, 17 }, + + /* 4000 */ { MAD_F(0x07c04056) /* 0.484436356 */, 17 }, + /* 4001 */ { MAD_F(0x07c0e9aa) /* 0.484597842 */, 17 }, + /* 4002 */ { MAD_F(0x07c19302) /* 0.484759341 */, 17 }, + /* 4003 */ { MAD_F(0x07c23c5e) /* 0.484920853 */, 17 }, + /* 4004 */ { MAD_F(0x07c2e5bd) /* 0.485082379 */, 17 }, + /* 4005 */ { MAD_F(0x07c38f20) /* 0.485243918 */, 17 }, + /* 4006 */ { MAD_F(0x07c43887) /* 0.485405471 */, 17 }, + /* 4007 */ { MAD_F(0x07c4e1f1) /* 0.485567037 */, 17 }, + /* 4008 */ { MAD_F(0x07c58b5f) /* 0.485728617 */, 17 }, + /* 4009 */ { MAD_F(0x07c634d0) /* 0.485890210 */, 17 }, + /* 4010 */ { MAD_F(0x07c6de45) /* 0.486051817 */, 17 }, + /* 4011 */ { MAD_F(0x07c787bd) /* 0.486213436 */, 17 }, + /* 4012 */ { MAD_F(0x07c83139) /* 0.486375070 */, 17 }, + /* 4013 */ { MAD_F(0x07c8dab9) /* 0.486536717 */, 17 }, + /* 4014 */ { MAD_F(0x07c9843c) /* 0.486698377 */, 17 }, + /* 4015 */ { MAD_F(0x07ca2dc3) /* 0.486860051 */, 17 }, + + /* 4016 */ { MAD_F(0x07cad74e) /* 0.487021738 */, 17 }, + /* 4017 */ { MAD_F(0x07cb80dc) /* 0.487183438 */, 17 }, + /* 4018 */ { MAD_F(0x07cc2a6e) /* 0.487345152 */, 17 }, + /* 4019 */ { MAD_F(0x07ccd403) /* 0.487506879 */, 17 }, + /* 4020 */ { MAD_F(0x07cd7d9c) /* 0.487668620 */, 17 }, + /* 4021 */ { MAD_F(0x07ce2739) /* 0.487830374 */, 17 }, + /* 4022 */ { MAD_F(0x07ced0d9) /* 0.487992142 */, 17 }, + /* 4023 */ { MAD_F(0x07cf7a7d) /* 0.488153923 */, 17 }, + /* 4024 */ { MAD_F(0x07d02424) /* 0.488315717 */, 17 }, + /* 4025 */ { MAD_F(0x07d0cdcf) /* 0.488477525 */, 17 }, + /* 4026 */ { MAD_F(0x07d1777e) /* 0.488639346 */, 17 }, + /* 4027 */ { MAD_F(0x07d22130) /* 0.488801181 */, 17 }, + /* 4028 */ { MAD_F(0x07d2cae5) /* 0.488963029 */, 17 }, + /* 4029 */ { MAD_F(0x07d3749f) /* 0.489124890 */, 17 }, + /* 4030 */ { MAD_F(0x07d41e5c) /* 0.489286765 */, 17 }, + /* 4031 */ { MAD_F(0x07d4c81c) /* 0.489448653 */, 17 }, + + /* 4032 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 17 }, + /* 4033 */ { MAD_F(0x07d61ba8) /* 0.489772470 */, 17 }, + /* 4034 */ { MAD_F(0x07d6c573) /* 0.489934398 */, 17 }, + /* 4035 */ { MAD_F(0x07d76f42) /* 0.490096340 */, 17 }, + /* 4036 */ { MAD_F(0x07d81915) /* 0.490258295 */, 17 }, + /* 4037 */ { MAD_F(0x07d8c2eb) /* 0.490420263 */, 17 }, + /* 4038 */ { MAD_F(0x07d96cc4) /* 0.490582245 */, 17 }, + /* 4039 */ { MAD_F(0x07da16a2) /* 0.490744240 */, 17 }, + /* 4040 */ { MAD_F(0x07dac083) /* 0.490906249 */, 17 }, + /* 4041 */ { MAD_F(0x07db6a67) /* 0.491068271 */, 17 }, + /* 4042 */ { MAD_F(0x07dc144f) /* 0.491230306 */, 17 }, + /* 4043 */ { MAD_F(0x07dcbe3b) /* 0.491392355 */, 17 }, + /* 4044 */ { MAD_F(0x07dd682a) /* 0.491554417 */, 17 }, + /* 4045 */ { MAD_F(0x07de121d) /* 0.491716492 */, 17 }, + /* 4046 */ { MAD_F(0x07debc13) /* 0.491878581 */, 17 }, + /* 4047 */ { MAD_F(0x07df660d) /* 0.492040683 */, 17 }, + + /* 4048 */ { MAD_F(0x07e0100a) /* 0.492202799 */, 17 }, + /* 4049 */ { MAD_F(0x07e0ba0c) /* 0.492364928 */, 17 }, + /* 4050 */ { MAD_F(0x07e16410) /* 0.492527070 */, 17 }, + /* 4051 */ { MAD_F(0x07e20e19) /* 0.492689225 */, 17 }, + /* 4052 */ { MAD_F(0x07e2b824) /* 0.492851394 */, 17 }, + /* 4053 */ { MAD_F(0x07e36234) /* 0.493013576 */, 17 }, + /* 4054 */ { MAD_F(0x07e40c47) /* 0.493175772 */, 17 }, + /* 4055 */ { MAD_F(0x07e4b65e) /* 0.493337981 */, 17 }, + /* 4056 */ { MAD_F(0x07e56078) /* 0.493500203 */, 17 }, + /* 4057 */ { MAD_F(0x07e60a95) /* 0.493662438 */, 17 }, + /* 4058 */ { MAD_F(0x07e6b4b7) /* 0.493824687 */, 17 }, + /* 4059 */ { MAD_F(0x07e75edc) /* 0.493986949 */, 17 }, + /* 4060 */ { MAD_F(0x07e80904) /* 0.494149225 */, 17 }, + /* 4061 */ { MAD_F(0x07e8b330) /* 0.494311514 */, 17 }, + /* 4062 */ { MAD_F(0x07e95d60) /* 0.494473816 */, 17 }, + /* 4063 */ { MAD_F(0x07ea0793) /* 0.494636131 */, 17 }, + + /* 4064 */ { MAD_F(0x07eab1ca) /* 0.494798460 */, 17 }, + /* 4065 */ { MAD_F(0x07eb5c04) /* 0.494960802 */, 17 }, + /* 4066 */ { MAD_F(0x07ec0642) /* 0.495123158 */, 17 }, + /* 4067 */ { MAD_F(0x07ecb084) /* 0.495285526 */, 17 }, + /* 4068 */ { MAD_F(0x07ed5ac9) /* 0.495447908 */, 17 }, + /* 4069 */ { MAD_F(0x07ee0512) /* 0.495610304 */, 17 }, + /* 4070 */ { MAD_F(0x07eeaf5e) /* 0.495772712 */, 17 }, + /* 4071 */ { MAD_F(0x07ef59ae) /* 0.495935134 */, 17 }, + /* 4072 */ { MAD_F(0x07f00401) /* 0.496097570 */, 17 }, + /* 4073 */ { MAD_F(0x07f0ae58) /* 0.496260018 */, 17 }, + /* 4074 */ { MAD_F(0x07f158b3) /* 0.496422480 */, 17 }, + /* 4075 */ { MAD_F(0x07f20311) /* 0.496584955 */, 17 }, + /* 4076 */ { MAD_F(0x07f2ad72) /* 0.496747444 */, 17 }, + /* 4077 */ { MAD_F(0x07f357d8) /* 0.496909945 */, 17 }, + /* 4078 */ { MAD_F(0x07f40240) /* 0.497072460 */, 17 }, + /* 4079 */ { MAD_F(0x07f4acad) /* 0.497234989 */, 17 }, + + /* 4080 */ { MAD_F(0x07f5571d) /* 0.497397530 */, 17 }, + /* 4081 */ { MAD_F(0x07f60190) /* 0.497560085 */, 17 }, + /* 4082 */ { MAD_F(0x07f6ac07) /* 0.497722653 */, 17 }, + /* 4083 */ { MAD_F(0x07f75682) /* 0.497885235 */, 17 }, + /* 4084 */ { MAD_F(0x07f80100) /* 0.498047829 */, 17 }, + /* 4085 */ { MAD_F(0x07f8ab82) /* 0.498210437 */, 17 }, + /* 4086 */ { MAD_F(0x07f95607) /* 0.498373058 */, 17 }, + /* 4087 */ { MAD_F(0x07fa0090) /* 0.498535693 */, 17 }, + /* 4088 */ { MAD_F(0x07faab1c) /* 0.498698341 */, 17 }, + /* 4089 */ { MAD_F(0x07fb55ac) /* 0.498861002 */, 17 }, + /* 4090 */ { MAD_F(0x07fc0040) /* 0.499023676 */, 17 }, + /* 4091 */ { MAD_F(0x07fcaad7) /* 0.499186364 */, 17 }, + /* 4092 */ { MAD_F(0x07fd5572) /* 0.499349064 */, 17 }, + /* 4093 */ { MAD_F(0x07fe0010) /* 0.499511778 */, 17 }, + /* 4094 */ { MAD_F(0x07feaab2) /* 0.499674506 */, 17 }, + /* 4095 */ { MAD_F(0x07ff5557) /* 0.499837246 */, 17 }, + + /* 4096 */ { MAD_F(0x04000000) /* 0.250000000 */, 18 }, + /* 4097 */ { MAD_F(0x04005556) /* 0.250081384 */, 18 }, + /* 4098 */ { MAD_F(0x0400aaae) /* 0.250162774 */, 18 }, + /* 4099 */ { MAD_F(0x04010008) /* 0.250244170 */, 18 }, + /* 4100 */ { MAD_F(0x04015563) /* 0.250325574 */, 18 }, + /* 4101 */ { MAD_F(0x0401aac1) /* 0.250406984 */, 18 }, + /* 4102 */ { MAD_F(0x04020020) /* 0.250488400 */, 18 }, + /* 4103 */ { MAD_F(0x04025581) /* 0.250569824 */, 18 }, + /* 4104 */ { MAD_F(0x0402aae3) /* 0.250651254 */, 18 }, + /* 4105 */ { MAD_F(0x04030048) /* 0.250732690 */, 18 }, + /* 4106 */ { MAD_F(0x040355ae) /* 0.250814133 */, 18 }, + /* 4107 */ { MAD_F(0x0403ab16) /* 0.250895583 */, 18 }, + /* 4108 */ { MAD_F(0x04040080) /* 0.250977039 */, 18 }, + /* 4109 */ { MAD_F(0x040455eb) /* 0.251058502 */, 18 }, + /* 4110 */ { MAD_F(0x0404ab59) /* 0.251139971 */, 18 }, + /* 4111 */ { MAD_F(0x040500c8) /* 0.251221448 */, 18 }, + + /* 4112 */ { MAD_F(0x04055638) /* 0.251302930 */, 18 }, + /* 4113 */ { MAD_F(0x0405abab) /* 0.251384420 */, 18 }, + /* 4114 */ { MAD_F(0x0406011f) /* 0.251465916 */, 18 }, + /* 4115 */ { MAD_F(0x04065696) /* 0.251547418 */, 18 }, + /* 4116 */ { MAD_F(0x0406ac0e) /* 0.251628927 */, 18 }, + /* 4117 */ { MAD_F(0x04070187) /* 0.251710443 */, 18 }, + /* 4118 */ { MAD_F(0x04075703) /* 0.251791965 */, 18 }, + /* 4119 */ { MAD_F(0x0407ac80) /* 0.251873494 */, 18 }, + /* 4120 */ { MAD_F(0x040801ff) /* 0.251955030 */, 18 }, + /* 4121 */ { MAD_F(0x04085780) /* 0.252036572 */, 18 }, + /* 4122 */ { MAD_F(0x0408ad02) /* 0.252118121 */, 18 }, + /* 4123 */ { MAD_F(0x04090287) /* 0.252199676 */, 18 }, + /* 4124 */ { MAD_F(0x0409580d) /* 0.252281238 */, 18 }, + /* 4125 */ { MAD_F(0x0409ad95) /* 0.252362807 */, 18 }, + /* 4126 */ { MAD_F(0x040a031e) /* 0.252444382 */, 18 }, + /* 4127 */ { MAD_F(0x040a58aa) /* 0.252525963 */, 18 }, + + /* 4128 */ { MAD_F(0x040aae37) /* 0.252607552 */, 18 }, + /* 4129 */ { MAD_F(0x040b03c6) /* 0.252689147 */, 18 }, + /* 4130 */ { MAD_F(0x040b5957) /* 0.252770748 */, 18 }, + /* 4131 */ { MAD_F(0x040baee9) /* 0.252852356 */, 18 }, + /* 4132 */ { MAD_F(0x040c047e) /* 0.252933971 */, 18 }, + /* 4133 */ { MAD_F(0x040c5a14) /* 0.253015592 */, 18 }, + /* 4134 */ { MAD_F(0x040cafab) /* 0.253097220 */, 18 }, + /* 4135 */ { MAD_F(0x040d0545) /* 0.253178854 */, 18 }, + /* 4136 */ { MAD_F(0x040d5ae0) /* 0.253260495 */, 18 }, + /* 4137 */ { MAD_F(0x040db07d) /* 0.253342143 */, 18 }, + /* 4138 */ { MAD_F(0x040e061c) /* 0.253423797 */, 18 }, + /* 4139 */ { MAD_F(0x040e5bbd) /* 0.253505457 */, 18 }, + /* 4140 */ { MAD_F(0x040eb15f) /* 0.253587125 */, 18 }, + /* 4141 */ { MAD_F(0x040f0703) /* 0.253668799 */, 18 }, + /* 4142 */ { MAD_F(0x040f5ca9) /* 0.253750479 */, 18 }, + /* 4143 */ { MAD_F(0x040fb251) /* 0.253832166 */, 18 }, + + /* 4144 */ { MAD_F(0x041007fa) /* 0.253913860 */, 18 }, + /* 4145 */ { MAD_F(0x04105da6) /* 0.253995560 */, 18 }, + /* 4146 */ { MAD_F(0x0410b353) /* 0.254077266 */, 18 }, + /* 4147 */ { MAD_F(0x04110901) /* 0.254158980 */, 18 }, + /* 4148 */ { MAD_F(0x04115eb2) /* 0.254240700 */, 18 }, + /* 4149 */ { MAD_F(0x0411b464) /* 0.254322426 */, 18 }, + /* 4150 */ { MAD_F(0x04120a18) /* 0.254404159 */, 18 }, + /* 4151 */ { MAD_F(0x04125fce) /* 0.254485899 */, 18 }, + /* 4152 */ { MAD_F(0x0412b586) /* 0.254567645 */, 18 }, + /* 4153 */ { MAD_F(0x04130b3f) /* 0.254649397 */, 18 }, + /* 4154 */ { MAD_F(0x041360fa) /* 0.254731157 */, 18 }, + /* 4155 */ { MAD_F(0x0413b6b7) /* 0.254812922 */, 18 }, + /* 4156 */ { MAD_F(0x04140c75) /* 0.254894695 */, 18 }, + /* 4157 */ { MAD_F(0x04146236) /* 0.254976474 */, 18 }, + /* 4158 */ { MAD_F(0x0414b7f8) /* 0.255058259 */, 18 }, + /* 4159 */ { MAD_F(0x04150dbc) /* 0.255140051 */, 18 }, + + /* 4160 */ { MAD_F(0x04156381) /* 0.255221850 */, 18 }, + /* 4161 */ { MAD_F(0x0415b949) /* 0.255303655 */, 18 }, + /* 4162 */ { MAD_F(0x04160f12) /* 0.255385467 */, 18 }, + /* 4163 */ { MAD_F(0x041664dd) /* 0.255467285 */, 18 }, + /* 4164 */ { MAD_F(0x0416baaa) /* 0.255549110 */, 18 }, + /* 4165 */ { MAD_F(0x04171078) /* 0.255630941 */, 18 }, + /* 4166 */ { MAD_F(0x04176648) /* 0.255712779 */, 18 }, + /* 4167 */ { MAD_F(0x0417bc1a) /* 0.255794624 */, 18 }, + /* 4168 */ { MAD_F(0x041811ee) /* 0.255876475 */, 18 }, + /* 4169 */ { MAD_F(0x041867c3) /* 0.255958332 */, 18 }, + /* 4170 */ { MAD_F(0x0418bd9b) /* 0.256040196 */, 18 }, + /* 4171 */ { MAD_F(0x04191374) /* 0.256122067 */, 18 }, + /* 4172 */ { MAD_F(0x0419694e) /* 0.256203944 */, 18 }, + /* 4173 */ { MAD_F(0x0419bf2b) /* 0.256285828 */, 18 }, + /* 4174 */ { MAD_F(0x041a1509) /* 0.256367718 */, 18 }, + /* 4175 */ { MAD_F(0x041a6ae9) /* 0.256449615 */, 18 }, + + /* 4176 */ { MAD_F(0x041ac0cb) /* 0.256531518 */, 18 }, + /* 4177 */ { MAD_F(0x041b16ae) /* 0.256613428 */, 18 }, + /* 4178 */ { MAD_F(0x041b6c94) /* 0.256695344 */, 18 }, + /* 4179 */ { MAD_F(0x041bc27b) /* 0.256777267 */, 18 }, + /* 4180 */ { MAD_F(0x041c1863) /* 0.256859197 */, 18 }, + /* 4181 */ { MAD_F(0x041c6e4e) /* 0.256941133 */, 18 }, + /* 4182 */ { MAD_F(0x041cc43a) /* 0.257023076 */, 18 }, + /* 4183 */ { MAD_F(0x041d1a28) /* 0.257105025 */, 18 }, + /* 4184 */ { MAD_F(0x041d7018) /* 0.257186980 */, 18 }, + /* 4185 */ { MAD_F(0x041dc60a) /* 0.257268942 */, 18 }, + /* 4186 */ { MAD_F(0x041e1bfd) /* 0.257350911 */, 18 }, + /* 4187 */ { MAD_F(0x041e71f2) /* 0.257432886 */, 18 }, + /* 4188 */ { MAD_F(0x041ec7e9) /* 0.257514868 */, 18 }, + /* 4189 */ { MAD_F(0x041f1de1) /* 0.257596856 */, 18 }, + /* 4190 */ { MAD_F(0x041f73dc) /* 0.257678851 */, 18 }, + /* 4191 */ { MAD_F(0x041fc9d8) /* 0.257760852 */, 18 }, + + /* 4192 */ { MAD_F(0x04201fd5) /* 0.257842860 */, 18 }, + /* 4193 */ { MAD_F(0x042075d5) /* 0.257924875 */, 18 }, + /* 4194 */ { MAD_F(0x0420cbd6) /* 0.258006895 */, 18 }, + /* 4195 */ { MAD_F(0x042121d9) /* 0.258088923 */, 18 }, + /* 4196 */ { MAD_F(0x042177de) /* 0.258170957 */, 18 }, + /* 4197 */ { MAD_F(0x0421cde5) /* 0.258252997 */, 18 }, + /* 4198 */ { MAD_F(0x042223ed) /* 0.258335044 */, 18 }, + /* 4199 */ { MAD_F(0x042279f7) /* 0.258417097 */, 18 }, + /* 4200 */ { MAD_F(0x0422d003) /* 0.258499157 */, 18 }, + /* 4201 */ { MAD_F(0x04232611) /* 0.258581224 */, 18 }, + /* 4202 */ { MAD_F(0x04237c20) /* 0.258663297 */, 18 }, + /* 4203 */ { MAD_F(0x0423d231) /* 0.258745376 */, 18 }, + /* 4204 */ { MAD_F(0x04242844) /* 0.258827462 */, 18 }, + /* 4205 */ { MAD_F(0x04247e58) /* 0.258909555 */, 18 }, + /* 4206 */ { MAD_F(0x0424d46e) /* 0.258991654 */, 18 }, + /* 4207 */ { MAD_F(0x04252a87) /* 0.259073760 */, 18 }, + + /* 4208 */ { MAD_F(0x042580a0) /* 0.259155872 */, 18 }, + /* 4209 */ { MAD_F(0x0425d6bc) /* 0.259237990 */, 18 }, + /* 4210 */ { MAD_F(0x04262cd9) /* 0.259320115 */, 18 }, + /* 4211 */ { MAD_F(0x042682f8) /* 0.259402247 */, 18 }, + /* 4212 */ { MAD_F(0x0426d919) /* 0.259484385 */, 18 }, + /* 4213 */ { MAD_F(0x04272f3b) /* 0.259566529 */, 18 }, + /* 4214 */ { MAD_F(0x04278560) /* 0.259648680 */, 18 }, + /* 4215 */ { MAD_F(0x0427db86) /* 0.259730838 */, 18 }, + /* 4216 */ { MAD_F(0x042831ad) /* 0.259813002 */, 18 }, + /* 4217 */ { MAD_F(0x042887d7) /* 0.259895173 */, 18 }, + /* 4218 */ { MAD_F(0x0428de02) /* 0.259977350 */, 18 }, + /* 4219 */ { MAD_F(0x0429342f) /* 0.260059533 */, 18 }, + /* 4220 */ { MAD_F(0x04298a5e) /* 0.260141723 */, 18 }, + /* 4221 */ { MAD_F(0x0429e08e) /* 0.260223920 */, 18 }, + /* 4222 */ { MAD_F(0x042a36c0) /* 0.260306123 */, 18 }, + /* 4223 */ { MAD_F(0x042a8cf4) /* 0.260388332 */, 18 }, + + /* 4224 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 18 }, + /* 4225 */ { MAD_F(0x042b3962) /* 0.260552771 */, 18 }, + /* 4226 */ { MAD_F(0x042b8f9b) /* 0.260635000 */, 18 }, + /* 4227 */ { MAD_F(0x042be5d6) /* 0.260717235 */, 18 }, + /* 4228 */ { MAD_F(0x042c3c12) /* 0.260799477 */, 18 }, + /* 4229 */ { MAD_F(0x042c9251) /* 0.260881725 */, 18 }, + /* 4230 */ { MAD_F(0x042ce891) /* 0.260963980 */, 18 }, + /* 4231 */ { MAD_F(0x042d3ed3) /* 0.261046242 */, 18 }, + /* 4232 */ { MAD_F(0x042d9516) /* 0.261128510 */, 18 }, + /* 4233 */ { MAD_F(0x042deb5c) /* 0.261210784 */, 18 }, + /* 4234 */ { MAD_F(0x042e41a3) /* 0.261293065 */, 18 }, + /* 4235 */ { MAD_F(0x042e97ec) /* 0.261375352 */, 18 }, + /* 4236 */ { MAD_F(0x042eee36) /* 0.261457646 */, 18 }, + /* 4237 */ { MAD_F(0x042f4482) /* 0.261539946 */, 18 }, + /* 4238 */ { MAD_F(0x042f9ad1) /* 0.261622253 */, 18 }, + /* 4239 */ { MAD_F(0x042ff120) /* 0.261704566 */, 18 }, + + /* 4240 */ { MAD_F(0x04304772) /* 0.261786886 */, 18 }, + /* 4241 */ { MAD_F(0x04309dc5) /* 0.261869212 */, 18 }, + /* 4242 */ { MAD_F(0x0430f41a) /* 0.261951545 */, 18 }, + /* 4243 */ { MAD_F(0x04314a71) /* 0.262033884 */, 18 }, + /* 4244 */ { MAD_F(0x0431a0c9) /* 0.262116229 */, 18 }, + /* 4245 */ { MAD_F(0x0431f723) /* 0.262198581 */, 18 }, + /* 4246 */ { MAD_F(0x04324d7f) /* 0.262280940 */, 18 }, + /* 4247 */ { MAD_F(0x0432a3dd) /* 0.262363305 */, 18 }, + /* 4248 */ { MAD_F(0x0432fa3d) /* 0.262445676 */, 18 }, + /* 4249 */ { MAD_F(0x0433509e) /* 0.262528054 */, 18 }, + /* 4250 */ { MAD_F(0x0433a701) /* 0.262610438 */, 18 }, + /* 4251 */ { MAD_F(0x0433fd65) /* 0.262692829 */, 18 }, + /* 4252 */ { MAD_F(0x043453cc) /* 0.262775227 */, 18 }, + /* 4253 */ { MAD_F(0x0434aa34) /* 0.262857630 */, 18 }, + /* 4254 */ { MAD_F(0x0435009d) /* 0.262940040 */, 18 }, + /* 4255 */ { MAD_F(0x04355709) /* 0.263022457 */, 18 }, + + /* 4256 */ { MAD_F(0x0435ad76) /* 0.263104880 */, 18 }, + /* 4257 */ { MAD_F(0x043603e5) /* 0.263187310 */, 18 }, + /* 4258 */ { MAD_F(0x04365a56) /* 0.263269746 */, 18 }, + /* 4259 */ { MAD_F(0x0436b0c9) /* 0.263352188 */, 18 }, + /* 4260 */ { MAD_F(0x0437073d) /* 0.263434637 */, 18 }, + /* 4261 */ { MAD_F(0x04375db3) /* 0.263517093 */, 18 }, + /* 4262 */ { MAD_F(0x0437b42a) /* 0.263599554 */, 18 }, + /* 4263 */ { MAD_F(0x04380aa4) /* 0.263682023 */, 18 }, + /* 4264 */ { MAD_F(0x0438611f) /* 0.263764497 */, 18 }, + /* 4265 */ { MAD_F(0x0438b79c) /* 0.263846979 */, 18 }, + /* 4266 */ { MAD_F(0x04390e1a) /* 0.263929466 */, 18 }, + /* 4267 */ { MAD_F(0x0439649b) /* 0.264011960 */, 18 }, + /* 4268 */ { MAD_F(0x0439bb1d) /* 0.264094461 */, 18 }, + /* 4269 */ { MAD_F(0x043a11a1) /* 0.264176968 */, 18 }, + /* 4270 */ { MAD_F(0x043a6826) /* 0.264259481 */, 18 }, + /* 4271 */ { MAD_F(0x043abead) /* 0.264342001 */, 18 }, + + /* 4272 */ { MAD_F(0x043b1536) /* 0.264424527 */, 18 }, + /* 4273 */ { MAD_F(0x043b6bc1) /* 0.264507060 */, 18 }, + /* 4274 */ { MAD_F(0x043bc24d) /* 0.264589599 */, 18 }, + /* 4275 */ { MAD_F(0x043c18dc) /* 0.264672145 */, 18 }, + /* 4276 */ { MAD_F(0x043c6f6c) /* 0.264754697 */, 18 }, + /* 4277 */ { MAD_F(0x043cc5fd) /* 0.264837255 */, 18 }, + /* 4278 */ { MAD_F(0x043d1c91) /* 0.264919820 */, 18 }, + /* 4279 */ { MAD_F(0x043d7326) /* 0.265002392 */, 18 }, + /* 4280 */ { MAD_F(0x043dc9bc) /* 0.265084969 */, 18 }, + /* 4281 */ { MAD_F(0x043e2055) /* 0.265167554 */, 18 }, + /* 4282 */ { MAD_F(0x043e76ef) /* 0.265250144 */, 18 }, + /* 4283 */ { MAD_F(0x043ecd8b) /* 0.265332741 */, 18 }, + /* 4284 */ { MAD_F(0x043f2429) /* 0.265415345 */, 18 }, + /* 4285 */ { MAD_F(0x043f7ac8) /* 0.265497955 */, 18 }, + /* 4286 */ { MAD_F(0x043fd169) /* 0.265580571 */, 18 }, + /* 4287 */ { MAD_F(0x0440280c) /* 0.265663194 */, 18 }, + + /* 4288 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 18 }, + /* 4289 */ { MAD_F(0x0440d557) /* 0.265828459 */, 18 }, + /* 4290 */ { MAD_F(0x04412bff) /* 0.265911101 */, 18 }, + /* 4291 */ { MAD_F(0x044182a9) /* 0.265993749 */, 18 }, + /* 4292 */ { MAD_F(0x0441d955) /* 0.266076404 */, 18 }, + /* 4293 */ { MAD_F(0x04423002) /* 0.266159065 */, 18 }, + /* 4294 */ { MAD_F(0x044286b1) /* 0.266241733 */, 18 }, + /* 4295 */ { MAD_F(0x0442dd61) /* 0.266324407 */, 18 }, + /* 4296 */ { MAD_F(0x04433414) /* 0.266407088 */, 18 }, + /* 4297 */ { MAD_F(0x04438ac8) /* 0.266489775 */, 18 }, + /* 4298 */ { MAD_F(0x0443e17e) /* 0.266572468 */, 18 }, + /* 4299 */ { MAD_F(0x04443835) /* 0.266655168 */, 18 }, + /* 4300 */ { MAD_F(0x04448eef) /* 0.266737874 */, 18 }, + /* 4301 */ { MAD_F(0x0444e5aa) /* 0.266820587 */, 18 }, + /* 4302 */ { MAD_F(0x04453c66) /* 0.266903306 */, 18 }, + /* 4303 */ { MAD_F(0x04459325) /* 0.266986031 */, 18 }, + + /* 4304 */ { MAD_F(0x0445e9e5) /* 0.267068763 */, 18 }, + /* 4305 */ { MAD_F(0x044640a7) /* 0.267151501 */, 18 }, + /* 4306 */ { MAD_F(0x0446976a) /* 0.267234246 */, 18 }, + /* 4307 */ { MAD_F(0x0446ee30) /* 0.267316997 */, 18 }, + /* 4308 */ { MAD_F(0x044744f7) /* 0.267399755 */, 18 }, + /* 4309 */ { MAD_F(0x04479bc0) /* 0.267482518 */, 18 }, + /* 4310 */ { MAD_F(0x0447f28a) /* 0.267565289 */, 18 }, + /* 4311 */ { MAD_F(0x04484956) /* 0.267648065 */, 18 }, + /* 4312 */ { MAD_F(0x0448a024) /* 0.267730848 */, 18 }, + /* 4313 */ { MAD_F(0x0448f6f4) /* 0.267813638 */, 18 }, + /* 4314 */ { MAD_F(0x04494dc5) /* 0.267896434 */, 18 }, + /* 4315 */ { MAD_F(0x0449a498) /* 0.267979236 */, 18 }, + /* 4316 */ { MAD_F(0x0449fb6d) /* 0.268062045 */, 18 }, + /* 4317 */ { MAD_F(0x044a5243) /* 0.268144860 */, 18 }, + /* 4318 */ { MAD_F(0x044aa91c) /* 0.268227681 */, 18 }, + /* 4319 */ { MAD_F(0x044afff6) /* 0.268310509 */, 18 }, + + /* 4320 */ { MAD_F(0x044b56d1) /* 0.268393343 */, 18 }, + /* 4321 */ { MAD_F(0x044badaf) /* 0.268476184 */, 18 }, + /* 4322 */ { MAD_F(0x044c048e) /* 0.268559031 */, 18 }, + /* 4323 */ { MAD_F(0x044c5b6f) /* 0.268641885 */, 18 }, + /* 4324 */ { MAD_F(0x044cb251) /* 0.268724744 */, 18 }, + /* 4325 */ { MAD_F(0x044d0935) /* 0.268807611 */, 18 }, + /* 4326 */ { MAD_F(0x044d601b) /* 0.268890483 */, 18 }, + /* 4327 */ { MAD_F(0x044db703) /* 0.268973362 */, 18 }, + /* 4328 */ { MAD_F(0x044e0dec) /* 0.269056248 */, 18 }, + /* 4329 */ { MAD_F(0x044e64d7) /* 0.269139139 */, 18 }, + /* 4330 */ { MAD_F(0x044ebbc4) /* 0.269222037 */, 18 }, + /* 4331 */ { MAD_F(0x044f12b3) /* 0.269304942 */, 18 }, + /* 4332 */ { MAD_F(0x044f69a3) /* 0.269387853 */, 18 }, + /* 4333 */ { MAD_F(0x044fc095) /* 0.269470770 */, 18 }, + /* 4334 */ { MAD_F(0x04501788) /* 0.269553694 */, 18 }, + /* 4335 */ { MAD_F(0x04506e7e) /* 0.269636624 */, 18 }, + + /* 4336 */ { MAD_F(0x0450c575) /* 0.269719560 */, 18 }, + /* 4337 */ { MAD_F(0x04511c6e) /* 0.269802503 */, 18 }, + /* 4338 */ { MAD_F(0x04517368) /* 0.269885452 */, 18 }, + /* 4339 */ { MAD_F(0x0451ca64) /* 0.269968408 */, 18 }, + /* 4340 */ { MAD_F(0x04522162) /* 0.270051370 */, 18 }, + /* 4341 */ { MAD_F(0x04527862) /* 0.270134338 */, 18 }, + /* 4342 */ { MAD_F(0x0452cf63) /* 0.270217312 */, 18 }, + /* 4343 */ { MAD_F(0x04532666) /* 0.270300293 */, 18 }, + /* 4344 */ { MAD_F(0x04537d6b) /* 0.270383281 */, 18 }, + /* 4345 */ { MAD_F(0x0453d472) /* 0.270466275 */, 18 }, + /* 4346 */ { MAD_F(0x04542b7a) /* 0.270549275 */, 18 }, + /* 4347 */ { MAD_F(0x04548284) /* 0.270632281 */, 18 }, + /* 4348 */ { MAD_F(0x0454d98f) /* 0.270715294 */, 18 }, + /* 4349 */ { MAD_F(0x0455309c) /* 0.270798313 */, 18 }, + /* 4350 */ { MAD_F(0x045587ab) /* 0.270881339 */, 18 }, + /* 4351 */ { MAD_F(0x0455debc) /* 0.270964371 */, 18 }, + + /* 4352 */ { MAD_F(0x045635cf) /* 0.271047409 */, 18 }, + /* 4353 */ { MAD_F(0x04568ce3) /* 0.271130454 */, 18 }, + /* 4354 */ { MAD_F(0x0456e3f9) /* 0.271213505 */, 18 }, + /* 4355 */ { MAD_F(0x04573b10) /* 0.271296562 */, 18 }, + /* 4356 */ { MAD_F(0x04579229) /* 0.271379626 */, 18 }, + /* 4357 */ { MAD_F(0x0457e944) /* 0.271462696 */, 18 }, + /* 4358 */ { MAD_F(0x04584061) /* 0.271545772 */, 18 }, + /* 4359 */ { MAD_F(0x0458977f) /* 0.271628855 */, 18 }, + /* 4360 */ { MAD_F(0x0458ee9f) /* 0.271711944 */, 18 }, + /* 4361 */ { MAD_F(0x045945c1) /* 0.271795040 */, 18 }, + /* 4362 */ { MAD_F(0x04599ce5) /* 0.271878142 */, 18 }, + /* 4363 */ { MAD_F(0x0459f40a) /* 0.271961250 */, 18 }, + /* 4364 */ { MAD_F(0x045a4b31) /* 0.272044365 */, 18 }, + /* 4365 */ { MAD_F(0x045aa259) /* 0.272127486 */, 18 }, + /* 4366 */ { MAD_F(0x045af984) /* 0.272210613 */, 18 }, + /* 4367 */ { MAD_F(0x045b50b0) /* 0.272293746 */, 18 }, + + /* 4368 */ { MAD_F(0x045ba7dd) /* 0.272376886 */, 18 }, + /* 4369 */ { MAD_F(0x045bff0d) /* 0.272460033 */, 18 }, + /* 4370 */ { MAD_F(0x045c563e) /* 0.272543185 */, 18 }, + /* 4371 */ { MAD_F(0x045cad71) /* 0.272626344 */, 18 }, + /* 4372 */ { MAD_F(0x045d04a5) /* 0.272709510 */, 18 }, + /* 4373 */ { MAD_F(0x045d5bdc) /* 0.272792681 */, 18 }, + /* 4374 */ { MAD_F(0x045db313) /* 0.272875859 */, 18 }, + /* 4375 */ { MAD_F(0x045e0a4d) /* 0.272959044 */, 18 }, + /* 4376 */ { MAD_F(0x045e6188) /* 0.273042234 */, 18 }, + /* 4377 */ { MAD_F(0x045eb8c5) /* 0.273125431 */, 18 }, + /* 4378 */ { MAD_F(0x045f1004) /* 0.273208635 */, 18 }, + /* 4379 */ { MAD_F(0x045f6745) /* 0.273291844 */, 18 }, + /* 4380 */ { MAD_F(0x045fbe87) /* 0.273375060 */, 18 }, + /* 4381 */ { MAD_F(0x046015cb) /* 0.273458283 */, 18 }, + /* 4382 */ { MAD_F(0x04606d10) /* 0.273541511 */, 18 }, + /* 4383 */ { MAD_F(0x0460c457) /* 0.273624747 */, 18 }, + + /* 4384 */ { MAD_F(0x04611ba0) /* 0.273707988 */, 18 }, + /* 4385 */ { MAD_F(0x046172eb) /* 0.273791236 */, 18 }, + /* 4386 */ { MAD_F(0x0461ca37) /* 0.273874490 */, 18 }, + /* 4387 */ { MAD_F(0x04622185) /* 0.273957750 */, 18 }, + /* 4388 */ { MAD_F(0x046278d5) /* 0.274041017 */, 18 }, + /* 4389 */ { MAD_F(0x0462d026) /* 0.274124290 */, 18 }, + /* 4390 */ { MAD_F(0x0463277a) /* 0.274207569 */, 18 }, + /* 4391 */ { MAD_F(0x04637ece) /* 0.274290855 */, 18 }, + /* 4392 */ { MAD_F(0x0463d625) /* 0.274374147 */, 18 }, + /* 4393 */ { MAD_F(0x04642d7d) /* 0.274457445 */, 18 }, + /* 4394 */ { MAD_F(0x046484d7) /* 0.274540749 */, 18 }, + /* 4395 */ { MAD_F(0x0464dc33) /* 0.274624060 */, 18 }, + /* 4396 */ { MAD_F(0x04653390) /* 0.274707378 */, 18 }, + /* 4397 */ { MAD_F(0x04658aef) /* 0.274790701 */, 18 }, + /* 4398 */ { MAD_F(0x0465e250) /* 0.274874031 */, 18 }, + /* 4399 */ { MAD_F(0x046639b2) /* 0.274957367 */, 18 }, + + /* 4400 */ { MAD_F(0x04669116) /* 0.275040710 */, 18 }, + /* 4401 */ { MAD_F(0x0466e87c) /* 0.275124059 */, 18 }, + /* 4402 */ { MAD_F(0x04673fe3) /* 0.275207414 */, 18 }, + /* 4403 */ { MAD_F(0x0467974d) /* 0.275290775 */, 18 }, + /* 4404 */ { MAD_F(0x0467eeb7) /* 0.275374143 */, 18 }, + /* 4405 */ { MAD_F(0x04684624) /* 0.275457517 */, 18 }, + /* 4406 */ { MAD_F(0x04689d92) /* 0.275540897 */, 18 }, + /* 4407 */ { MAD_F(0x0468f502) /* 0.275624284 */, 18 }, + /* 4408 */ { MAD_F(0x04694c74) /* 0.275707677 */, 18 }, + /* 4409 */ { MAD_F(0x0469a3e7) /* 0.275791076 */, 18 }, + /* 4410 */ { MAD_F(0x0469fb5c) /* 0.275874482 */, 18 }, + /* 4411 */ { MAD_F(0x046a52d3) /* 0.275957894 */, 18 }, + /* 4412 */ { MAD_F(0x046aaa4b) /* 0.276041312 */, 18 }, + /* 4413 */ { MAD_F(0x046b01c5) /* 0.276124737 */, 18 }, + /* 4414 */ { MAD_F(0x046b5941) /* 0.276208167 */, 18 }, + /* 4415 */ { MAD_F(0x046bb0bf) /* 0.276291605 */, 18 }, + + /* 4416 */ { MAD_F(0x046c083e) /* 0.276375048 */, 18 }, + /* 4417 */ { MAD_F(0x046c5fbf) /* 0.276458498 */, 18 }, + /* 4418 */ { MAD_F(0x046cb741) /* 0.276541954 */, 18 }, + /* 4419 */ { MAD_F(0x046d0ec5) /* 0.276625416 */, 18 }, + /* 4420 */ { MAD_F(0x046d664b) /* 0.276708885 */, 18 }, + /* 4421 */ { MAD_F(0x046dbdd3) /* 0.276792360 */, 18 }, + /* 4422 */ { MAD_F(0x046e155c) /* 0.276875841 */, 18 }, + /* 4423 */ { MAD_F(0x046e6ce7) /* 0.276959328 */, 18 }, + /* 4424 */ { MAD_F(0x046ec474) /* 0.277042822 */, 18 }, + /* 4425 */ { MAD_F(0x046f1c02) /* 0.277126322 */, 18 }, + /* 4426 */ { MAD_F(0x046f7392) /* 0.277209829 */, 18 }, + /* 4427 */ { MAD_F(0x046fcb24) /* 0.277293341 */, 18 }, + /* 4428 */ { MAD_F(0x047022b8) /* 0.277376860 */, 18 }, + /* 4429 */ { MAD_F(0x04707a4d) /* 0.277460385 */, 18 }, + /* 4430 */ { MAD_F(0x0470d1e4) /* 0.277543917 */, 18 }, + /* 4431 */ { MAD_F(0x0471297c) /* 0.277627455 */, 18 }, + + /* 4432 */ { MAD_F(0x04718116) /* 0.277710999 */, 18 }, + /* 4433 */ { MAD_F(0x0471d8b2) /* 0.277794549 */, 18 }, + /* 4434 */ { MAD_F(0x04723050) /* 0.277878106 */, 18 }, + /* 4435 */ { MAD_F(0x047287ef) /* 0.277961669 */, 18 }, + /* 4436 */ { MAD_F(0x0472df90) /* 0.278045238 */, 18 }, + /* 4437 */ { MAD_F(0x04733733) /* 0.278128813 */, 18 }, + /* 4438 */ { MAD_F(0x04738ed7) /* 0.278212395 */, 18 }, + /* 4439 */ { MAD_F(0x0473e67d) /* 0.278295983 */, 18 }, + /* 4440 */ { MAD_F(0x04743e25) /* 0.278379578 */, 18 }, + /* 4441 */ { MAD_F(0x047495ce) /* 0.278463178 */, 18 }, + /* 4442 */ { MAD_F(0x0474ed79) /* 0.278546785 */, 18 }, + /* 4443 */ { MAD_F(0x04754526) /* 0.278630398 */, 18 }, + /* 4444 */ { MAD_F(0x04759cd4) /* 0.278714018 */, 18 }, + /* 4445 */ { MAD_F(0x0475f484) /* 0.278797643 */, 18 }, + /* 4446 */ { MAD_F(0x04764c36) /* 0.278881275 */, 18 }, + /* 4447 */ { MAD_F(0x0476a3ea) /* 0.278964914 */, 18 }, + + /* 4448 */ { MAD_F(0x0476fb9f) /* 0.279048558 */, 18 }, + /* 4449 */ { MAD_F(0x04775356) /* 0.279132209 */, 18 }, + /* 4450 */ { MAD_F(0x0477ab0e) /* 0.279215866 */, 18 }, + /* 4451 */ { MAD_F(0x047802c8) /* 0.279299529 */, 18 }, + /* 4452 */ { MAD_F(0x04785a84) /* 0.279383199 */, 18 }, + /* 4453 */ { MAD_F(0x0478b242) /* 0.279466875 */, 18 }, + /* 4454 */ { MAD_F(0x04790a01) /* 0.279550557 */, 18 }, + /* 4455 */ { MAD_F(0x047961c2) /* 0.279634245 */, 18 }, + /* 4456 */ { MAD_F(0x0479b984) /* 0.279717940 */, 18 }, + /* 4457 */ { MAD_F(0x047a1149) /* 0.279801641 */, 18 }, + /* 4458 */ { MAD_F(0x047a690f) /* 0.279885348 */, 18 }, + /* 4459 */ { MAD_F(0x047ac0d6) /* 0.279969061 */, 18 }, + /* 4460 */ { MAD_F(0x047b18a0) /* 0.280052781 */, 18 }, + /* 4461 */ { MAD_F(0x047b706b) /* 0.280136507 */, 18 }, + /* 4462 */ { MAD_F(0x047bc837) /* 0.280220239 */, 18 }, + /* 4463 */ { MAD_F(0x047c2006) /* 0.280303978 */, 18 }, + + /* 4464 */ { MAD_F(0x047c77d6) /* 0.280387722 */, 18 }, + /* 4465 */ { MAD_F(0x047ccfa8) /* 0.280471473 */, 18 }, + /* 4466 */ { MAD_F(0x047d277b) /* 0.280555230 */, 18 }, + /* 4467 */ { MAD_F(0x047d7f50) /* 0.280638994 */, 18 }, + /* 4468 */ { MAD_F(0x047dd727) /* 0.280722764 */, 18 }, + /* 4469 */ { MAD_F(0x047e2eff) /* 0.280806540 */, 18 }, + /* 4470 */ { MAD_F(0x047e86d9) /* 0.280890322 */, 18 }, + /* 4471 */ { MAD_F(0x047edeb5) /* 0.280974110 */, 18 }, + /* 4472 */ { MAD_F(0x047f3693) /* 0.281057905 */, 18 }, + /* 4473 */ { MAD_F(0x047f8e72) /* 0.281141706 */, 18 }, + /* 4474 */ { MAD_F(0x047fe653) /* 0.281225513 */, 18 }, + /* 4475 */ { MAD_F(0x04803e35) /* 0.281309326 */, 18 }, + /* 4476 */ { MAD_F(0x04809619) /* 0.281393146 */, 18 }, + /* 4477 */ { MAD_F(0x0480edff) /* 0.281476972 */, 18 }, + /* 4478 */ { MAD_F(0x048145e7) /* 0.281560804 */, 18 }, + /* 4479 */ { MAD_F(0x04819dd0) /* 0.281644643 */, 18 }, + + /* 4480 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 18 }, + /* 4481 */ { MAD_F(0x04824da7) /* 0.281812338 */, 18 }, + /* 4482 */ { MAD_F(0x0482a595) /* 0.281896195 */, 18 }, + /* 4483 */ { MAD_F(0x0482fd85) /* 0.281980059 */, 18 }, + /* 4484 */ { MAD_F(0x04835577) /* 0.282063928 */, 18 }, + /* 4485 */ { MAD_F(0x0483ad6a) /* 0.282147804 */, 18 }, + /* 4486 */ { MAD_F(0x0484055f) /* 0.282231686 */, 18 }, + /* 4487 */ { MAD_F(0x04845d56) /* 0.282315574 */, 18 }, + /* 4488 */ { MAD_F(0x0484b54e) /* 0.282399469 */, 18 }, + /* 4489 */ { MAD_F(0x04850d48) /* 0.282483370 */, 18 }, + /* 4490 */ { MAD_F(0x04856544) /* 0.282567277 */, 18 }, + /* 4491 */ { MAD_F(0x0485bd41) /* 0.282651190 */, 18 }, + /* 4492 */ { MAD_F(0x04861540) /* 0.282735109 */, 18 }, + /* 4493 */ { MAD_F(0x04866d40) /* 0.282819035 */, 18 }, + /* 4494 */ { MAD_F(0x0486c543) /* 0.282902967 */, 18 }, + /* 4495 */ { MAD_F(0x04871d47) /* 0.282986905 */, 18 }, + + /* 4496 */ { MAD_F(0x0487754c) /* 0.283070849 */, 18 }, + /* 4497 */ { MAD_F(0x0487cd54) /* 0.283154800 */, 18 }, + /* 4498 */ { MAD_F(0x0488255d) /* 0.283238757 */, 18 }, + /* 4499 */ { MAD_F(0x04887d67) /* 0.283322720 */, 18 }, + /* 4500 */ { MAD_F(0x0488d574) /* 0.283406689 */, 18 }, + /* 4501 */ { MAD_F(0x04892d82) /* 0.283490665 */, 18 }, + /* 4502 */ { MAD_F(0x04898591) /* 0.283574646 */, 18 }, + /* 4503 */ { MAD_F(0x0489dda3) /* 0.283658634 */, 18 }, + /* 4504 */ { MAD_F(0x048a35b6) /* 0.283742628 */, 18 }, + /* 4505 */ { MAD_F(0x048a8dca) /* 0.283826629 */, 18 }, + /* 4506 */ { MAD_F(0x048ae5e1) /* 0.283910635 */, 18 }, + /* 4507 */ { MAD_F(0x048b3df9) /* 0.283994648 */, 18 }, + /* 4508 */ { MAD_F(0x048b9612) /* 0.284078667 */, 18 }, + /* 4509 */ { MAD_F(0x048bee2e) /* 0.284162692 */, 18 }, + /* 4510 */ { MAD_F(0x048c464b) /* 0.284246723 */, 18 }, + /* 4511 */ { MAD_F(0x048c9e69) /* 0.284330761 */, 18 }, + + /* 4512 */ { MAD_F(0x048cf68a) /* 0.284414805 */, 18 }, + /* 4513 */ { MAD_F(0x048d4eac) /* 0.284498855 */, 18 }, + /* 4514 */ { MAD_F(0x048da6cf) /* 0.284582911 */, 18 }, + /* 4515 */ { MAD_F(0x048dfef5) /* 0.284666974 */, 18 }, + /* 4516 */ { MAD_F(0x048e571c) /* 0.284751042 */, 18 }, + /* 4517 */ { MAD_F(0x048eaf44) /* 0.284835117 */, 18 }, + /* 4518 */ { MAD_F(0x048f076f) /* 0.284919198 */, 18 }, + /* 4519 */ { MAD_F(0x048f5f9b) /* 0.285003285 */, 18 }, + /* 4520 */ { MAD_F(0x048fb7c8) /* 0.285087379 */, 18 }, + /* 4521 */ { MAD_F(0x04900ff8) /* 0.285171479 */, 18 }, + /* 4522 */ { MAD_F(0x04906829) /* 0.285255584 */, 18 }, + /* 4523 */ { MAD_F(0x0490c05b) /* 0.285339697 */, 18 }, + /* 4524 */ { MAD_F(0x04911890) /* 0.285423815 */, 18 }, + /* 4525 */ { MAD_F(0x049170c6) /* 0.285507939 */, 18 }, + /* 4526 */ { MAD_F(0x0491c8fd) /* 0.285592070 */, 18 }, + /* 4527 */ { MAD_F(0x04922137) /* 0.285676207 */, 18 }, + + /* 4528 */ { MAD_F(0x04927972) /* 0.285760350 */, 18 }, + /* 4529 */ { MAD_F(0x0492d1ae) /* 0.285844499 */, 18 }, + /* 4530 */ { MAD_F(0x049329ed) /* 0.285928655 */, 18 }, + /* 4531 */ { MAD_F(0x0493822c) /* 0.286012816 */, 18 }, + /* 4532 */ { MAD_F(0x0493da6e) /* 0.286096984 */, 18 }, + /* 4533 */ { MAD_F(0x049432b1) /* 0.286181158 */, 18 }, + /* 4534 */ { MAD_F(0x04948af6) /* 0.286265338 */, 18 }, + /* 4535 */ { MAD_F(0x0494e33d) /* 0.286349525 */, 18 }, + /* 4536 */ { MAD_F(0x04953b85) /* 0.286433717 */, 18 }, + /* 4537 */ { MAD_F(0x049593cf) /* 0.286517916 */, 18 }, + /* 4538 */ { MAD_F(0x0495ec1b) /* 0.286602121 */, 18 }, + /* 4539 */ { MAD_F(0x04964468) /* 0.286686332 */, 18 }, + /* 4540 */ { MAD_F(0x04969cb7) /* 0.286770550 */, 18 }, + /* 4541 */ { MAD_F(0x0496f508) /* 0.286854773 */, 18 }, + /* 4542 */ { MAD_F(0x04974d5a) /* 0.286939003 */, 18 }, + /* 4543 */ { MAD_F(0x0497a5ae) /* 0.287023239 */, 18 }, + + /* 4544 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 18 }, + /* 4545 */ { MAD_F(0x0498565a) /* 0.287191729 */, 18 }, + /* 4546 */ { MAD_F(0x0498aeb3) /* 0.287275983 */, 18 }, + /* 4547 */ { MAD_F(0x0499070e) /* 0.287360244 */, 18 }, + /* 4548 */ { MAD_F(0x04995f6a) /* 0.287444511 */, 18 }, + /* 4549 */ { MAD_F(0x0499b7c8) /* 0.287528784 */, 18 }, + /* 4550 */ { MAD_F(0x049a1027) /* 0.287613063 */, 18 }, + /* 4551 */ { MAD_F(0x049a6889) /* 0.287697348 */, 18 }, + /* 4552 */ { MAD_F(0x049ac0eb) /* 0.287781640 */, 18 }, + /* 4553 */ { MAD_F(0x049b1950) /* 0.287865937 */, 18 }, + /* 4554 */ { MAD_F(0x049b71b6) /* 0.287950241 */, 18 }, + /* 4555 */ { MAD_F(0x049bca1e) /* 0.288034551 */, 18 }, + /* 4556 */ { MAD_F(0x049c2287) /* 0.288118867 */, 18 }, + /* 4557 */ { MAD_F(0x049c7af2) /* 0.288203190 */, 18 }, + /* 4558 */ { MAD_F(0x049cd35f) /* 0.288287518 */, 18 }, + /* 4559 */ { MAD_F(0x049d2bce) /* 0.288371853 */, 18 }, + + /* 4560 */ { MAD_F(0x049d843e) /* 0.288456194 */, 18 }, + /* 4561 */ { MAD_F(0x049ddcaf) /* 0.288540541 */, 18 }, + /* 4562 */ { MAD_F(0x049e3523) /* 0.288624894 */, 18 }, + /* 4563 */ { MAD_F(0x049e8d98) /* 0.288709253 */, 18 }, + /* 4564 */ { MAD_F(0x049ee60e) /* 0.288793619 */, 18 }, + /* 4565 */ { MAD_F(0x049f3e87) /* 0.288877990 */, 18 }, + /* 4566 */ { MAD_F(0x049f9701) /* 0.288962368 */, 18 }, + /* 4567 */ { MAD_F(0x049fef7c) /* 0.289046752 */, 18 }, + /* 4568 */ { MAD_F(0x04a047fa) /* 0.289131142 */, 18 }, + /* 4569 */ { MAD_F(0x04a0a079) /* 0.289215538 */, 18 }, + /* 4570 */ { MAD_F(0x04a0f8f9) /* 0.289299941 */, 18 }, + /* 4571 */ { MAD_F(0x04a1517c) /* 0.289384349 */, 18 }, + /* 4572 */ { MAD_F(0x04a1a9ff) /* 0.289468764 */, 18 }, + /* 4573 */ { MAD_F(0x04a20285) /* 0.289553185 */, 18 }, + /* 4574 */ { MAD_F(0x04a25b0c) /* 0.289637612 */, 18 }, + /* 4575 */ { MAD_F(0x04a2b395) /* 0.289722045 */, 18 }, + + /* 4576 */ { MAD_F(0x04a30c20) /* 0.289806485 */, 18 }, + /* 4577 */ { MAD_F(0x04a364ac) /* 0.289890930 */, 18 }, + /* 4578 */ { MAD_F(0x04a3bd3a) /* 0.289975382 */, 18 }, + /* 4579 */ { MAD_F(0x04a415c9) /* 0.290059840 */, 18 }, + /* 4580 */ { MAD_F(0x04a46e5a) /* 0.290144304 */, 18 }, + /* 4581 */ { MAD_F(0x04a4c6ed) /* 0.290228774 */, 18 }, + /* 4582 */ { MAD_F(0x04a51f81) /* 0.290313250 */, 18 }, + /* 4583 */ { MAD_F(0x04a57818) /* 0.290397733 */, 18 }, + /* 4584 */ { MAD_F(0x04a5d0af) /* 0.290482221 */, 18 }, + /* 4585 */ { MAD_F(0x04a62949) /* 0.290566716 */, 18 }, + /* 4586 */ { MAD_F(0x04a681e4) /* 0.290651217 */, 18 }, + /* 4587 */ { MAD_F(0x04a6da80) /* 0.290735724 */, 18 }, + /* 4588 */ { MAD_F(0x04a7331f) /* 0.290820237 */, 18 }, + /* 4589 */ { MAD_F(0x04a78bbf) /* 0.290904756 */, 18 }, + /* 4590 */ { MAD_F(0x04a7e460) /* 0.290989281 */, 18 }, + /* 4591 */ { MAD_F(0x04a83d03) /* 0.291073813 */, 18 }, + + /* 4592 */ { MAD_F(0x04a895a8) /* 0.291158351 */, 18 }, + /* 4593 */ { MAD_F(0x04a8ee4f) /* 0.291242894 */, 18 }, + /* 4594 */ { MAD_F(0x04a946f7) /* 0.291327444 */, 18 }, + /* 4595 */ { MAD_F(0x04a99fa1) /* 0.291412001 */, 18 }, + /* 4596 */ { MAD_F(0x04a9f84c) /* 0.291496563 */, 18 }, + /* 4597 */ { MAD_F(0x04aa50fa) /* 0.291581131 */, 18 }, + /* 4598 */ { MAD_F(0x04aaa9a8) /* 0.291665706 */, 18 }, + /* 4599 */ { MAD_F(0x04ab0259) /* 0.291750286 */, 18 }, + /* 4600 */ { MAD_F(0x04ab5b0b) /* 0.291834873 */, 18 }, + /* 4601 */ { MAD_F(0x04abb3bf) /* 0.291919466 */, 18 }, + /* 4602 */ { MAD_F(0x04ac0c74) /* 0.292004065 */, 18 }, + /* 4603 */ { MAD_F(0x04ac652b) /* 0.292088670 */, 18 }, + /* 4604 */ { MAD_F(0x04acbde4) /* 0.292173281 */, 18 }, + /* 4605 */ { MAD_F(0x04ad169e) /* 0.292257899 */, 18 }, + /* 4606 */ { MAD_F(0x04ad6f5a) /* 0.292342522 */, 18 }, + /* 4607 */ { MAD_F(0x04adc818) /* 0.292427152 */, 18 }, + + /* 4608 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 18 }, + /* 4609 */ { MAD_F(0x04ae7998) /* 0.292596430 */, 18 }, + /* 4610 */ { MAD_F(0x04aed25a) /* 0.292681078 */, 18 }, + /* 4611 */ { MAD_F(0x04af2b1e) /* 0.292765732 */, 18 }, + /* 4612 */ { MAD_F(0x04af83e4) /* 0.292850392 */, 18 }, + /* 4613 */ { MAD_F(0x04afdcac) /* 0.292935058 */, 18 }, + /* 4614 */ { MAD_F(0x04b03575) /* 0.293019731 */, 18 }, + /* 4615 */ { MAD_F(0x04b08e40) /* 0.293104409 */, 18 }, + /* 4616 */ { MAD_F(0x04b0e70c) /* 0.293189094 */, 18 }, + /* 4617 */ { MAD_F(0x04b13fda) /* 0.293273785 */, 18 }, + /* 4618 */ { MAD_F(0x04b198aa) /* 0.293358482 */, 18 }, + /* 4619 */ { MAD_F(0x04b1f17b) /* 0.293443185 */, 18 }, + /* 4620 */ { MAD_F(0x04b24a4e) /* 0.293527894 */, 18 }, + /* 4621 */ { MAD_F(0x04b2a322) /* 0.293612609 */, 18 }, + /* 4622 */ { MAD_F(0x04b2fbf9) /* 0.293697331 */, 18 }, + /* 4623 */ { MAD_F(0x04b354d1) /* 0.293782058 */, 18 }, + + /* 4624 */ { MAD_F(0x04b3adaa) /* 0.293866792 */, 18 }, + /* 4625 */ { MAD_F(0x04b40685) /* 0.293951532 */, 18 }, + /* 4626 */ { MAD_F(0x04b45f62) /* 0.294036278 */, 18 }, + /* 4627 */ { MAD_F(0x04b4b840) /* 0.294121029 */, 18 }, + /* 4628 */ { MAD_F(0x04b51120) /* 0.294205788 */, 18 }, + /* 4629 */ { MAD_F(0x04b56a02) /* 0.294290552 */, 18 }, + /* 4630 */ { MAD_F(0x04b5c2e6) /* 0.294375322 */, 18 }, + /* 4631 */ { MAD_F(0x04b61bcb) /* 0.294460098 */, 18 }, + /* 4632 */ { MAD_F(0x04b674b1) /* 0.294544881 */, 18 }, + /* 4633 */ { MAD_F(0x04b6cd99) /* 0.294629669 */, 18 }, + /* 4634 */ { MAD_F(0x04b72683) /* 0.294714464 */, 18 }, + /* 4635 */ { MAD_F(0x04b77f6f) /* 0.294799265 */, 18 }, + /* 4636 */ { MAD_F(0x04b7d85c) /* 0.294884072 */, 18 }, + /* 4637 */ { MAD_F(0x04b8314b) /* 0.294968885 */, 18 }, + /* 4638 */ { MAD_F(0x04b88a3b) /* 0.295053704 */, 18 }, + /* 4639 */ { MAD_F(0x04b8e32d) /* 0.295138529 */, 18 }, + + /* 4640 */ { MAD_F(0x04b93c21) /* 0.295223360 */, 18 }, + /* 4641 */ { MAD_F(0x04b99516) /* 0.295308197 */, 18 }, + /* 4642 */ { MAD_F(0x04b9ee0d) /* 0.295393041 */, 18 }, + /* 4643 */ { MAD_F(0x04ba4706) /* 0.295477890 */, 18 }, + /* 4644 */ { MAD_F(0x04baa000) /* 0.295562746 */, 18 }, + /* 4645 */ { MAD_F(0x04baf8fc) /* 0.295647608 */, 18 }, + /* 4646 */ { MAD_F(0x04bb51fa) /* 0.295732476 */, 18 }, + /* 4647 */ { MAD_F(0x04bbaaf9) /* 0.295817349 */, 18 }, + /* 4648 */ { MAD_F(0x04bc03fa) /* 0.295902229 */, 18 }, + /* 4649 */ { MAD_F(0x04bc5cfc) /* 0.295987115 */, 18 }, + /* 4650 */ { MAD_F(0x04bcb600) /* 0.296072008 */, 18 }, + /* 4651 */ { MAD_F(0x04bd0f06) /* 0.296156906 */, 18 }, + /* 4652 */ { MAD_F(0x04bd680d) /* 0.296241810 */, 18 }, + /* 4653 */ { MAD_F(0x04bdc116) /* 0.296326721 */, 18 }, + /* 4654 */ { MAD_F(0x04be1a21) /* 0.296411637 */, 18 }, + /* 4655 */ { MAD_F(0x04be732d) /* 0.296496560 */, 18 }, + + /* 4656 */ { MAD_F(0x04becc3b) /* 0.296581488 */, 18 }, + /* 4657 */ { MAD_F(0x04bf254a) /* 0.296666423 */, 18 }, + /* 4658 */ { MAD_F(0x04bf7e5b) /* 0.296751364 */, 18 }, + /* 4659 */ { MAD_F(0x04bfd76e) /* 0.296836311 */, 18 }, + /* 4660 */ { MAD_F(0x04c03083) /* 0.296921264 */, 18 }, + /* 4661 */ { MAD_F(0x04c08999) /* 0.297006223 */, 18 }, + /* 4662 */ { MAD_F(0x04c0e2b0) /* 0.297091188 */, 18 }, + /* 4663 */ { MAD_F(0x04c13bca) /* 0.297176159 */, 18 }, + /* 4664 */ { MAD_F(0x04c194e4) /* 0.297261136 */, 18 }, + /* 4665 */ { MAD_F(0x04c1ee01) /* 0.297346120 */, 18 }, + /* 4666 */ { MAD_F(0x04c2471f) /* 0.297431109 */, 18 }, + /* 4667 */ { MAD_F(0x04c2a03f) /* 0.297516105 */, 18 }, + /* 4668 */ { MAD_F(0x04c2f960) /* 0.297601106 */, 18 }, + /* 4669 */ { MAD_F(0x04c35283) /* 0.297686114 */, 18 }, + /* 4670 */ { MAD_F(0x04c3aba8) /* 0.297771128 */, 18 }, + /* 4671 */ { MAD_F(0x04c404ce) /* 0.297856147 */, 18 }, + + /* 4672 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 18 }, + /* 4673 */ { MAD_F(0x04c4b720) /* 0.298026205 */, 18 }, + /* 4674 */ { MAD_F(0x04c5104b) /* 0.298111243 */, 18 }, + /* 4675 */ { MAD_F(0x04c56978) /* 0.298196287 */, 18 }, + /* 4676 */ { MAD_F(0x04c5c2a7) /* 0.298281337 */, 18 }, + /* 4677 */ { MAD_F(0x04c61bd7) /* 0.298366393 */, 18 }, + /* 4678 */ { MAD_F(0x04c67508) /* 0.298451456 */, 18 }, + /* 4679 */ { MAD_F(0x04c6ce3c) /* 0.298536524 */, 18 }, + /* 4680 */ { MAD_F(0x04c72771) /* 0.298621598 */, 18 }, + /* 4681 */ { MAD_F(0x04c780a7) /* 0.298706679 */, 18 }, + /* 4682 */ { MAD_F(0x04c7d9df) /* 0.298791765 */, 18 }, + /* 4683 */ { MAD_F(0x04c83319) /* 0.298876858 */, 18 }, + /* 4684 */ { MAD_F(0x04c88c55) /* 0.298961956 */, 18 }, + /* 4685 */ { MAD_F(0x04c8e592) /* 0.299047061 */, 18 }, + /* 4686 */ { MAD_F(0x04c93ed1) /* 0.299132172 */, 18 }, + /* 4687 */ { MAD_F(0x04c99811) /* 0.299217288 */, 18 }, + + /* 4688 */ { MAD_F(0x04c9f153) /* 0.299302411 */, 18 }, + /* 4689 */ { MAD_F(0x04ca4a97) /* 0.299387540 */, 18 }, + /* 4690 */ { MAD_F(0x04caa3dc) /* 0.299472675 */, 18 }, + /* 4691 */ { MAD_F(0x04cafd23) /* 0.299557816 */, 18 }, + /* 4692 */ { MAD_F(0x04cb566b) /* 0.299642963 */, 18 }, + /* 4693 */ { MAD_F(0x04cbafb5) /* 0.299728116 */, 18 }, + /* 4694 */ { MAD_F(0x04cc0901) /* 0.299813275 */, 18 }, + /* 4695 */ { MAD_F(0x04cc624e) /* 0.299898440 */, 18 }, + /* 4696 */ { MAD_F(0x04ccbb9d) /* 0.299983611 */, 18 }, + /* 4697 */ { MAD_F(0x04cd14ee) /* 0.300068789 */, 18 }, + /* 4698 */ { MAD_F(0x04cd6e40) /* 0.300153972 */, 18 }, + /* 4699 */ { MAD_F(0x04cdc794) /* 0.300239161 */, 18 }, + /* 4700 */ { MAD_F(0x04ce20e9) /* 0.300324357 */, 18 }, + /* 4701 */ { MAD_F(0x04ce7a40) /* 0.300409558 */, 18 }, + /* 4702 */ { MAD_F(0x04ced399) /* 0.300494765 */, 18 }, + /* 4703 */ { MAD_F(0x04cf2cf3) /* 0.300579979 */, 18 }, + + /* 4704 */ { MAD_F(0x04cf864f) /* 0.300665198 */, 18 }, + /* 4705 */ { MAD_F(0x04cfdfad) /* 0.300750424 */, 18 }, + /* 4706 */ { MAD_F(0x04d0390c) /* 0.300835656 */, 18 }, + /* 4707 */ { MAD_F(0x04d0926d) /* 0.300920893 */, 18 }, + /* 4708 */ { MAD_F(0x04d0ebcf) /* 0.301006137 */, 18 }, + /* 4709 */ { MAD_F(0x04d14533) /* 0.301091387 */, 18 }, + /* 4710 */ { MAD_F(0x04d19e99) /* 0.301176643 */, 18 }, + /* 4711 */ { MAD_F(0x04d1f800) /* 0.301261904 */, 18 }, + /* 4712 */ { MAD_F(0x04d25169) /* 0.301347172 */, 18 }, + /* 4713 */ { MAD_F(0x04d2aad4) /* 0.301432446 */, 18 }, + /* 4714 */ { MAD_F(0x04d30440) /* 0.301517726 */, 18 }, + /* 4715 */ { MAD_F(0x04d35dae) /* 0.301603012 */, 18 }, + /* 4716 */ { MAD_F(0x04d3b71d) /* 0.301688304 */, 18 }, + /* 4717 */ { MAD_F(0x04d4108e) /* 0.301773602 */, 18 }, + /* 4718 */ { MAD_F(0x04d46a01) /* 0.301858906 */, 18 }, + /* 4719 */ { MAD_F(0x04d4c375) /* 0.301944216 */, 18 }, + + /* 4720 */ { MAD_F(0x04d51ceb) /* 0.302029532 */, 18 }, + /* 4721 */ { MAD_F(0x04d57662) /* 0.302114854 */, 18 }, + /* 4722 */ { MAD_F(0x04d5cfdb) /* 0.302200182 */, 18 }, + /* 4723 */ { MAD_F(0x04d62956) /* 0.302285516 */, 18 }, + /* 4724 */ { MAD_F(0x04d682d2) /* 0.302370856 */, 18 }, + /* 4725 */ { MAD_F(0x04d6dc50) /* 0.302456203 */, 18 }, + /* 4726 */ { MAD_F(0x04d735d0) /* 0.302541555 */, 18 }, + /* 4727 */ { MAD_F(0x04d78f51) /* 0.302626913 */, 18 }, + /* 4728 */ { MAD_F(0x04d7e8d4) /* 0.302712277 */, 18 }, + /* 4729 */ { MAD_F(0x04d84258) /* 0.302797648 */, 18 }, + /* 4730 */ { MAD_F(0x04d89bde) /* 0.302883024 */, 18 }, + /* 4731 */ { MAD_F(0x04d8f566) /* 0.302968406 */, 18 }, + /* 4732 */ { MAD_F(0x04d94eef) /* 0.303053794 */, 18 }, + /* 4733 */ { MAD_F(0x04d9a87a) /* 0.303139189 */, 18 }, + /* 4734 */ { MAD_F(0x04da0207) /* 0.303224589 */, 18 }, + /* 4735 */ { MAD_F(0x04da5b95) /* 0.303309995 */, 18 }, + + /* 4736 */ { MAD_F(0x04dab524) /* 0.303395408 */, 18 }, + /* 4737 */ { MAD_F(0x04db0eb6) /* 0.303480826 */, 18 }, + /* 4738 */ { MAD_F(0x04db6849) /* 0.303566251 */, 18 }, + /* 4739 */ { MAD_F(0x04dbc1dd) /* 0.303651681 */, 18 }, + /* 4740 */ { MAD_F(0x04dc1b73) /* 0.303737117 */, 18 }, + /* 4741 */ { MAD_F(0x04dc750b) /* 0.303822560 */, 18 }, + /* 4742 */ { MAD_F(0x04dccea5) /* 0.303908008 */, 18 }, + /* 4743 */ { MAD_F(0x04dd2840) /* 0.303993463 */, 18 }, + /* 4744 */ { MAD_F(0x04dd81dc) /* 0.304078923 */, 18 }, + /* 4745 */ { MAD_F(0x04dddb7a) /* 0.304164390 */, 18 }, + /* 4746 */ { MAD_F(0x04de351a) /* 0.304249862 */, 18 }, + /* 4747 */ { MAD_F(0x04de8ebc) /* 0.304335340 */, 18 }, + /* 4748 */ { MAD_F(0x04dee85f) /* 0.304420825 */, 18 }, + /* 4749 */ { MAD_F(0x04df4203) /* 0.304506315 */, 18 }, + /* 4750 */ { MAD_F(0x04df9baa) /* 0.304591812 */, 18 }, + /* 4751 */ { MAD_F(0x04dff552) /* 0.304677314 */, 18 }, + + /* 4752 */ { MAD_F(0x04e04efb) /* 0.304762823 */, 18 }, + /* 4753 */ { MAD_F(0x04e0a8a6) /* 0.304848337 */, 18 }, + /* 4754 */ { MAD_F(0x04e10253) /* 0.304933858 */, 18 }, + /* 4755 */ { MAD_F(0x04e15c01) /* 0.305019384 */, 18 }, + /* 4756 */ { MAD_F(0x04e1b5b1) /* 0.305104917 */, 18 }, + /* 4757 */ { MAD_F(0x04e20f63) /* 0.305190455 */, 18 }, + /* 4758 */ { MAD_F(0x04e26916) /* 0.305275999 */, 18 }, + /* 4759 */ { MAD_F(0x04e2c2cb) /* 0.305361550 */, 18 }, + /* 4760 */ { MAD_F(0x04e31c81) /* 0.305447106 */, 18 }, + /* 4761 */ { MAD_F(0x04e37639) /* 0.305532669 */, 18 }, + /* 4762 */ { MAD_F(0x04e3cff3) /* 0.305618237 */, 18 }, + /* 4763 */ { MAD_F(0x04e429ae) /* 0.305703811 */, 18 }, + /* 4764 */ { MAD_F(0x04e4836b) /* 0.305789392 */, 18 }, + /* 4765 */ { MAD_F(0x04e4dd29) /* 0.305874978 */, 18 }, + /* 4766 */ { MAD_F(0x04e536e9) /* 0.305960571 */, 18 }, + /* 4767 */ { MAD_F(0x04e590ab) /* 0.306046169 */, 18 }, + + /* 4768 */ { MAD_F(0x04e5ea6e) /* 0.306131773 */, 18 }, + /* 4769 */ { MAD_F(0x04e64433) /* 0.306217383 */, 18 }, + /* 4770 */ { MAD_F(0x04e69df9) /* 0.306303000 */, 18 }, + /* 4771 */ { MAD_F(0x04e6f7c1) /* 0.306388622 */, 18 }, + /* 4772 */ { MAD_F(0x04e7518b) /* 0.306474250 */, 18 }, + /* 4773 */ { MAD_F(0x04e7ab56) /* 0.306559885 */, 18 }, + /* 4774 */ { MAD_F(0x04e80523) /* 0.306645525 */, 18 }, + /* 4775 */ { MAD_F(0x04e85ef2) /* 0.306731171 */, 18 }, + /* 4776 */ { MAD_F(0x04e8b8c2) /* 0.306816823 */, 18 }, + /* 4777 */ { MAD_F(0x04e91293) /* 0.306902481 */, 18 }, + /* 4778 */ { MAD_F(0x04e96c67) /* 0.306988145 */, 18 }, + /* 4779 */ { MAD_F(0x04e9c63b) /* 0.307073816 */, 18 }, + /* 4780 */ { MAD_F(0x04ea2012) /* 0.307159492 */, 18 }, + /* 4781 */ { MAD_F(0x04ea79ea) /* 0.307245174 */, 18 }, + /* 4782 */ { MAD_F(0x04ead3c4) /* 0.307330862 */, 18 }, + /* 4783 */ { MAD_F(0x04eb2d9f) /* 0.307416556 */, 18 }, + + /* 4784 */ { MAD_F(0x04eb877c) /* 0.307502256 */, 18 }, + /* 4785 */ { MAD_F(0x04ebe15b) /* 0.307587962 */, 18 }, + /* 4786 */ { MAD_F(0x04ec3b3b) /* 0.307673674 */, 18 }, + /* 4787 */ { MAD_F(0x04ec951c) /* 0.307759392 */, 18 }, + /* 4788 */ { MAD_F(0x04ecef00) /* 0.307845115 */, 18 }, + /* 4789 */ { MAD_F(0x04ed48e5) /* 0.307930845 */, 18 }, + /* 4790 */ { MAD_F(0x04eda2cb) /* 0.308016581 */, 18 }, + /* 4791 */ { MAD_F(0x04edfcb3) /* 0.308102323 */, 18 }, + /* 4792 */ { MAD_F(0x04ee569d) /* 0.308188071 */, 18 }, + /* 4793 */ { MAD_F(0x04eeb088) /* 0.308273824 */, 18 }, + /* 4794 */ { MAD_F(0x04ef0a75) /* 0.308359584 */, 18 }, + /* 4795 */ { MAD_F(0x04ef6464) /* 0.308445350 */, 18 }, + /* 4796 */ { MAD_F(0x04efbe54) /* 0.308531121 */, 18 }, + /* 4797 */ { MAD_F(0x04f01846) /* 0.308616899 */, 18 }, + /* 4798 */ { MAD_F(0x04f07239) /* 0.308702682 */, 18 }, + /* 4799 */ { MAD_F(0x04f0cc2e) /* 0.308788472 */, 18 }, + + /* 4800 */ { MAD_F(0x04f12624) /* 0.308874267 */, 18 }, + /* 4801 */ { MAD_F(0x04f1801d) /* 0.308960068 */, 18 }, + /* 4802 */ { MAD_F(0x04f1da16) /* 0.309045876 */, 18 }, + /* 4803 */ { MAD_F(0x04f23412) /* 0.309131689 */, 18 }, + /* 4804 */ { MAD_F(0x04f28e0f) /* 0.309217508 */, 18 }, + /* 4805 */ { MAD_F(0x04f2e80d) /* 0.309303334 */, 18 }, + /* 4806 */ { MAD_F(0x04f3420d) /* 0.309389165 */, 18 }, + /* 4807 */ { MAD_F(0x04f39c0f) /* 0.309475002 */, 18 }, + /* 4808 */ { MAD_F(0x04f3f612) /* 0.309560845 */, 18 }, + /* 4809 */ { MAD_F(0x04f45017) /* 0.309646694 */, 18 }, + /* 4810 */ { MAD_F(0x04f4aa1e) /* 0.309732549 */, 18 }, + /* 4811 */ { MAD_F(0x04f50426) /* 0.309818410 */, 18 }, + /* 4812 */ { MAD_F(0x04f55e30) /* 0.309904277 */, 18 }, + /* 4813 */ { MAD_F(0x04f5b83b) /* 0.309990150 */, 18 }, + /* 4814 */ { MAD_F(0x04f61248) /* 0.310076028 */, 18 }, + /* 4815 */ { MAD_F(0x04f66c56) /* 0.310161913 */, 18 }, + + /* 4816 */ { MAD_F(0x04f6c666) /* 0.310247804 */, 18 }, + /* 4817 */ { MAD_F(0x04f72078) /* 0.310333700 */, 18 }, + /* 4818 */ { MAD_F(0x04f77a8b) /* 0.310419603 */, 18 }, + /* 4819 */ { MAD_F(0x04f7d4a0) /* 0.310505511 */, 18 }, + /* 4820 */ { MAD_F(0x04f82eb7) /* 0.310591426 */, 18 }, + /* 4821 */ { MAD_F(0x04f888cf) /* 0.310677346 */, 18 }, + /* 4822 */ { MAD_F(0x04f8e2e9) /* 0.310763272 */, 18 }, + /* 4823 */ { MAD_F(0x04f93d04) /* 0.310849205 */, 18 }, + /* 4824 */ { MAD_F(0x04f99721) /* 0.310935143 */, 18 }, + /* 4825 */ { MAD_F(0x04f9f13f) /* 0.311021087 */, 18 }, + /* 4826 */ { MAD_F(0x04fa4b5f) /* 0.311107037 */, 18 }, + /* 4827 */ { MAD_F(0x04faa581) /* 0.311192993 */, 18 }, + /* 4828 */ { MAD_F(0x04faffa4) /* 0.311278955 */, 18 }, + /* 4829 */ { MAD_F(0x04fb59c9) /* 0.311364923 */, 18 }, + /* 4830 */ { MAD_F(0x04fbb3ef) /* 0.311450897 */, 18 }, + /* 4831 */ { MAD_F(0x04fc0e17) /* 0.311536877 */, 18 }, + + /* 4832 */ { MAD_F(0x04fc6841) /* 0.311622862 */, 18 }, + /* 4833 */ { MAD_F(0x04fcc26c) /* 0.311708854 */, 18 }, + /* 4834 */ { MAD_F(0x04fd1c99) /* 0.311794851 */, 18 }, + /* 4835 */ { MAD_F(0x04fd76c7) /* 0.311880855 */, 18 }, + /* 4836 */ { MAD_F(0x04fdd0f7) /* 0.311966864 */, 18 }, + /* 4837 */ { MAD_F(0x04fe2b29) /* 0.312052880 */, 18 }, + /* 4838 */ { MAD_F(0x04fe855c) /* 0.312138901 */, 18 }, + /* 4839 */ { MAD_F(0x04fedf91) /* 0.312224928 */, 18 }, + /* 4840 */ { MAD_F(0x04ff39c7) /* 0.312310961 */, 18 }, + /* 4841 */ { MAD_F(0x04ff93ff) /* 0.312397000 */, 18 }, + /* 4842 */ { MAD_F(0x04ffee38) /* 0.312483045 */, 18 }, + /* 4843 */ { MAD_F(0x05004874) /* 0.312569096 */, 18 }, + /* 4844 */ { MAD_F(0x0500a2b0) /* 0.312655153 */, 18 }, + /* 4845 */ { MAD_F(0x0500fcef) /* 0.312741216 */, 18 }, + /* 4846 */ { MAD_F(0x0501572e) /* 0.312827284 */, 18 }, + /* 4847 */ { MAD_F(0x0501b170) /* 0.312913359 */, 18 }, + + /* 4848 */ { MAD_F(0x05020bb3) /* 0.312999439 */, 18 }, + /* 4849 */ { MAD_F(0x050265f8) /* 0.313085526 */, 18 }, + /* 4850 */ { MAD_F(0x0502c03e) /* 0.313171618 */, 18 }, + /* 4851 */ { MAD_F(0x05031a86) /* 0.313257716 */, 18 }, + /* 4852 */ { MAD_F(0x050374cf) /* 0.313343820 */, 18 }, + /* 4853 */ { MAD_F(0x0503cf1a) /* 0.313429931 */, 18 }, + /* 4854 */ { MAD_F(0x05042967) /* 0.313516047 */, 18 }, + /* 4855 */ { MAD_F(0x050483b5) /* 0.313602168 */, 18 }, + /* 4856 */ { MAD_F(0x0504de05) /* 0.313688296 */, 18 }, + /* 4857 */ { MAD_F(0x05053856) /* 0.313774430 */, 18 }, + /* 4858 */ { MAD_F(0x050592a9) /* 0.313860570 */, 18 }, + /* 4859 */ { MAD_F(0x0505ecfd) /* 0.313946715 */, 18 }, + /* 4860 */ { MAD_F(0x05064754) /* 0.314032867 */, 18 }, + /* 4861 */ { MAD_F(0x0506a1ab) /* 0.314119024 */, 18 }, + /* 4862 */ { MAD_F(0x0506fc04) /* 0.314205187 */, 18 }, + /* 4863 */ { MAD_F(0x0507565f) /* 0.314291357 */, 18 }, + + /* 4864 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 18 }, + /* 4865 */ { MAD_F(0x05080b1a) /* 0.314463713 */, 18 }, + /* 4866 */ { MAD_F(0x05086579) /* 0.314549900 */, 18 }, + /* 4867 */ { MAD_F(0x0508bfdb) /* 0.314636092 */, 18 }, + /* 4868 */ { MAD_F(0x05091a3d) /* 0.314722291 */, 18 }, + /* 4869 */ { MAD_F(0x050974a2) /* 0.314808496 */, 18 }, + /* 4870 */ { MAD_F(0x0509cf08) /* 0.314894706 */, 18 }, + /* 4871 */ { MAD_F(0x050a296f) /* 0.314980923 */, 18 }, + /* 4872 */ { MAD_F(0x050a83d8) /* 0.315067145 */, 18 }, + /* 4873 */ { MAD_F(0x050ade43) /* 0.315153373 */, 18 }, + /* 4874 */ { MAD_F(0x050b38af) /* 0.315239607 */, 18 }, + /* 4875 */ { MAD_F(0x050b931d) /* 0.315325847 */, 18 }, + /* 4876 */ { MAD_F(0x050bed8d) /* 0.315412093 */, 18 }, + /* 4877 */ { MAD_F(0x050c47fe) /* 0.315498345 */, 18 }, + /* 4878 */ { MAD_F(0x050ca271) /* 0.315584603 */, 18 }, + /* 4879 */ { MAD_F(0x050cfce5) /* 0.315670866 */, 18 }, + + /* 4880 */ { MAD_F(0x050d575b) /* 0.315757136 */, 18 }, + /* 4881 */ { MAD_F(0x050db1d2) /* 0.315843411 */, 18 }, + /* 4882 */ { MAD_F(0x050e0c4b) /* 0.315929693 */, 18 }, + /* 4883 */ { MAD_F(0x050e66c5) /* 0.316015980 */, 18 }, + /* 4884 */ { MAD_F(0x050ec141) /* 0.316102273 */, 18 }, + /* 4885 */ { MAD_F(0x050f1bbf) /* 0.316188572 */, 18 }, + /* 4886 */ { MAD_F(0x050f763e) /* 0.316274877 */, 18 }, + /* 4887 */ { MAD_F(0x050fd0bf) /* 0.316361187 */, 18 }, + /* 4888 */ { MAD_F(0x05102b42) /* 0.316447504 */, 18 }, + /* 4889 */ { MAD_F(0x051085c6) /* 0.316533826 */, 18 }, + /* 4890 */ { MAD_F(0x0510e04b) /* 0.316620155 */, 18 }, + /* 4891 */ { MAD_F(0x05113ad3) /* 0.316706489 */, 18 }, + /* 4892 */ { MAD_F(0x0511955b) /* 0.316792829 */, 18 }, + /* 4893 */ { MAD_F(0x0511efe6) /* 0.316879175 */, 18 }, + /* 4894 */ { MAD_F(0x05124a72) /* 0.316965527 */, 18 }, + /* 4895 */ { MAD_F(0x0512a4ff) /* 0.317051885 */, 18 }, + + /* 4896 */ { MAD_F(0x0512ff8e) /* 0.317138249 */, 18 }, + /* 4897 */ { MAD_F(0x05135a1f) /* 0.317224618 */, 18 }, + /* 4898 */ { MAD_F(0x0513b4b1) /* 0.317310994 */, 18 }, + /* 4899 */ { MAD_F(0x05140f45) /* 0.317397375 */, 18 }, + /* 4900 */ { MAD_F(0x051469da) /* 0.317483762 */, 18 }, + /* 4901 */ { MAD_F(0x0514c471) /* 0.317570155 */, 18 }, + /* 4902 */ { MAD_F(0x05151f0a) /* 0.317656554 */, 18 }, + /* 4903 */ { MAD_F(0x051579a4) /* 0.317742959 */, 18 }, + /* 4904 */ { MAD_F(0x0515d440) /* 0.317829370 */, 18 }, + /* 4905 */ { MAD_F(0x05162edd) /* 0.317915786 */, 18 }, + /* 4906 */ { MAD_F(0x0516897c) /* 0.318002209 */, 18 }, + /* 4907 */ { MAD_F(0x0516e41c) /* 0.318088637 */, 18 }, + /* 4908 */ { MAD_F(0x05173ebe) /* 0.318175071 */, 18 }, + /* 4909 */ { MAD_F(0x05179962) /* 0.318261511 */, 18 }, + /* 4910 */ { MAD_F(0x0517f407) /* 0.318347957 */, 18 }, + /* 4911 */ { MAD_F(0x05184eae) /* 0.318434409 */, 18 }, + + /* 4912 */ { MAD_F(0x0518a956) /* 0.318520867 */, 18 }, + /* 4913 */ { MAD_F(0x05190400) /* 0.318607330 */, 18 }, + /* 4914 */ { MAD_F(0x05195eab) /* 0.318693800 */, 18 }, + /* 4915 */ { MAD_F(0x0519b958) /* 0.318780275 */, 18 }, + /* 4916 */ { MAD_F(0x051a1407) /* 0.318866756 */, 18 }, + /* 4917 */ { MAD_F(0x051a6eb7) /* 0.318953243 */, 18 }, + /* 4918 */ { MAD_F(0x051ac969) /* 0.319039736 */, 18 }, + /* 4919 */ { MAD_F(0x051b241c) /* 0.319126235 */, 18 }, + /* 4920 */ { MAD_F(0x051b7ed1) /* 0.319212739 */, 18 }, + /* 4921 */ { MAD_F(0x051bd987) /* 0.319299250 */, 18 }, + /* 4922 */ { MAD_F(0x051c3440) /* 0.319385766 */, 18 }, + /* 4923 */ { MAD_F(0x051c8ef9) /* 0.319472288 */, 18 }, + /* 4924 */ { MAD_F(0x051ce9b4) /* 0.319558816 */, 18 }, + /* 4925 */ { MAD_F(0x051d4471) /* 0.319645350 */, 18 }, + /* 4926 */ { MAD_F(0x051d9f2f) /* 0.319731890 */, 18 }, + /* 4927 */ { MAD_F(0x051df9ef) /* 0.319818435 */, 18 }, + + /* 4928 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 18 }, + /* 4929 */ { MAD_F(0x051eaf74) /* 0.319991544 */, 18 }, + /* 4930 */ { MAD_F(0x051f0a38) /* 0.320078107 */, 18 }, + /* 4931 */ { MAD_F(0x051f64ff) /* 0.320164676 */, 18 }, + /* 4932 */ { MAD_F(0x051fbfc6) /* 0.320251251 */, 18 }, + /* 4933 */ { MAD_F(0x05201a90) /* 0.320337832 */, 18 }, + /* 4934 */ { MAD_F(0x0520755b) /* 0.320424419 */, 18 }, + /* 4935 */ { MAD_F(0x0520d027) /* 0.320511011 */, 18 }, + /* 4936 */ { MAD_F(0x05212af5) /* 0.320597609 */, 18 }, + /* 4937 */ { MAD_F(0x052185c5) /* 0.320684213 */, 18 }, + /* 4938 */ { MAD_F(0x0521e096) /* 0.320770823 */, 18 }, + /* 4939 */ { MAD_F(0x05223b69) /* 0.320857439 */, 18 }, + /* 4940 */ { MAD_F(0x0522963d) /* 0.320944061 */, 18 }, + /* 4941 */ { MAD_F(0x0522f113) /* 0.321030688 */, 18 }, + /* 4942 */ { MAD_F(0x05234bea) /* 0.321117322 */, 18 }, + /* 4943 */ { MAD_F(0x0523a6c3) /* 0.321203961 */, 18 }, + + /* 4944 */ { MAD_F(0x0524019e) /* 0.321290606 */, 18 }, + /* 4945 */ { MAD_F(0x05245c7a) /* 0.321377257 */, 18 }, + /* 4946 */ { MAD_F(0x0524b758) /* 0.321463913 */, 18 }, + /* 4947 */ { MAD_F(0x05251237) /* 0.321550576 */, 18 }, + /* 4948 */ { MAD_F(0x05256d18) /* 0.321637244 */, 18 }, + /* 4949 */ { MAD_F(0x0525c7fb) /* 0.321723919 */, 18 }, + /* 4950 */ { MAD_F(0x052622df) /* 0.321810599 */, 18 }, + /* 4951 */ { MAD_F(0x05267dc4) /* 0.321897285 */, 18 }, + /* 4952 */ { MAD_F(0x0526d8ab) /* 0.321983976 */, 18 }, + /* 4953 */ { MAD_F(0x05273394) /* 0.322070674 */, 18 }, + /* 4954 */ { MAD_F(0x05278e7e) /* 0.322157377 */, 18 }, + /* 4955 */ { MAD_F(0x0527e96a) /* 0.322244087 */, 18 }, + /* 4956 */ { MAD_F(0x05284457) /* 0.322330802 */, 18 }, + /* 4957 */ { MAD_F(0x05289f46) /* 0.322417523 */, 18 }, + /* 4958 */ { MAD_F(0x0528fa37) /* 0.322504249 */, 18 }, + /* 4959 */ { MAD_F(0x05295529) /* 0.322590982 */, 18 }, + + /* 4960 */ { MAD_F(0x0529b01d) /* 0.322677720 */, 18 }, + /* 4961 */ { MAD_F(0x052a0b12) /* 0.322764465 */, 18 }, + /* 4962 */ { MAD_F(0x052a6609) /* 0.322851215 */, 18 }, + /* 4963 */ { MAD_F(0x052ac101) /* 0.322937971 */, 18 }, + /* 4964 */ { MAD_F(0x052b1bfb) /* 0.323024732 */, 18 }, + /* 4965 */ { MAD_F(0x052b76f7) /* 0.323111500 */, 18 }, + /* 4966 */ { MAD_F(0x052bd1f4) /* 0.323198273 */, 18 }, + /* 4967 */ { MAD_F(0x052c2cf2) /* 0.323285052 */, 18 }, + /* 4968 */ { MAD_F(0x052c87f2) /* 0.323371837 */, 18 }, + /* 4969 */ { MAD_F(0x052ce2f4) /* 0.323458628 */, 18 }, + /* 4970 */ { MAD_F(0x052d3df7) /* 0.323545425 */, 18 }, + /* 4971 */ { MAD_F(0x052d98fc) /* 0.323632227 */, 18 }, + /* 4972 */ { MAD_F(0x052df403) /* 0.323719036 */, 18 }, + /* 4973 */ { MAD_F(0x052e4f0b) /* 0.323805850 */, 18 }, + /* 4974 */ { MAD_F(0x052eaa14) /* 0.323892670 */, 18 }, + /* 4975 */ { MAD_F(0x052f051f) /* 0.323979496 */, 18 }, + + /* 4976 */ { MAD_F(0x052f602c) /* 0.324066327 */, 18 }, + /* 4977 */ { MAD_F(0x052fbb3a) /* 0.324153165 */, 18 }, + /* 4978 */ { MAD_F(0x0530164a) /* 0.324240008 */, 18 }, + /* 4979 */ { MAD_F(0x0530715b) /* 0.324326857 */, 18 }, + /* 4980 */ { MAD_F(0x0530cc6e) /* 0.324413712 */, 18 }, + /* 4981 */ { MAD_F(0x05312783) /* 0.324500572 */, 18 }, + /* 4982 */ { MAD_F(0x05318299) /* 0.324587439 */, 18 }, + /* 4983 */ { MAD_F(0x0531ddb0) /* 0.324674311 */, 18 }, + /* 4984 */ { MAD_F(0x053238ca) /* 0.324761189 */, 18 }, + /* 4985 */ { MAD_F(0x053293e4) /* 0.324848073 */, 18 }, + /* 4986 */ { MAD_F(0x0532ef01) /* 0.324934963 */, 18 }, + /* 4987 */ { MAD_F(0x05334a1e) /* 0.325021858 */, 18 }, + /* 4988 */ { MAD_F(0x0533a53e) /* 0.325108760 */, 18 }, + /* 4989 */ { MAD_F(0x0534005f) /* 0.325195667 */, 18 }, + /* 4990 */ { MAD_F(0x05345b81) /* 0.325282580 */, 18 }, + /* 4991 */ { MAD_F(0x0534b6a5) /* 0.325369498 */, 18 }, + + /* 4992 */ { MAD_F(0x053511cb) /* 0.325456423 */, 18 }, + /* 4993 */ { MAD_F(0x05356cf2) /* 0.325543353 */, 18 }, + /* 4994 */ { MAD_F(0x0535c81b) /* 0.325630290 */, 18 }, + /* 4995 */ { MAD_F(0x05362345) /* 0.325717232 */, 18 }, + /* 4996 */ { MAD_F(0x05367e71) /* 0.325804179 */, 18 }, + /* 4997 */ { MAD_F(0x0536d99f) /* 0.325891133 */, 18 }, + /* 4998 */ { MAD_F(0x053734ce) /* 0.325978092 */, 18 }, + /* 4999 */ { MAD_F(0x05378ffe) /* 0.326065057 */, 18 }, + /* 5000 */ { MAD_F(0x0537eb30) /* 0.326152028 */, 18 }, + /* 5001 */ { MAD_F(0x05384664) /* 0.326239005 */, 18 }, + /* 5002 */ { MAD_F(0x0538a199) /* 0.326325988 */, 18 }, + /* 5003 */ { MAD_F(0x0538fcd0) /* 0.326412976 */, 18 }, + /* 5004 */ { MAD_F(0x05395808) /* 0.326499970 */, 18 }, + /* 5005 */ { MAD_F(0x0539b342) /* 0.326586970 */, 18 }, + /* 5006 */ { MAD_F(0x053a0e7d) /* 0.326673976 */, 18 }, + /* 5007 */ { MAD_F(0x053a69ba) /* 0.326760988 */, 18 }, + + /* 5008 */ { MAD_F(0x053ac4f9) /* 0.326848005 */, 18 }, + /* 5009 */ { MAD_F(0x053b2039) /* 0.326935028 */, 18 }, + /* 5010 */ { MAD_F(0x053b7b7b) /* 0.327022057 */, 18 }, + /* 5011 */ { MAD_F(0x053bd6be) /* 0.327109092 */, 18 }, + /* 5012 */ { MAD_F(0x053c3203) /* 0.327196132 */, 18 }, + /* 5013 */ { MAD_F(0x053c8d49) /* 0.327283178 */, 18 }, + /* 5014 */ { MAD_F(0x053ce891) /* 0.327370231 */, 18 }, + /* 5015 */ { MAD_F(0x053d43da) /* 0.327457288 */, 18 }, + /* 5016 */ { MAD_F(0x053d9f25) /* 0.327544352 */, 18 }, + /* 5017 */ { MAD_F(0x053dfa72) /* 0.327631421 */, 18 }, + /* 5018 */ { MAD_F(0x053e55c0) /* 0.327718497 */, 18 }, + /* 5019 */ { MAD_F(0x053eb10f) /* 0.327805578 */, 18 }, + /* 5020 */ { MAD_F(0x053f0c61) /* 0.327892665 */, 18 }, + /* 5021 */ { MAD_F(0x053f67b3) /* 0.327979757 */, 18 }, + /* 5022 */ { MAD_F(0x053fc308) /* 0.328066855 */, 18 }, + /* 5023 */ { MAD_F(0x05401e5e) /* 0.328153960 */, 18 }, + + /* 5024 */ { MAD_F(0x054079b5) /* 0.328241070 */, 18 }, + /* 5025 */ { MAD_F(0x0540d50e) /* 0.328328185 */, 18 }, + /* 5026 */ { MAD_F(0x05413068) /* 0.328415307 */, 18 }, + /* 5027 */ { MAD_F(0x05418bc4) /* 0.328502434 */, 18 }, + /* 5028 */ { MAD_F(0x0541e722) /* 0.328589567 */, 18 }, + /* 5029 */ { MAD_F(0x05424281) /* 0.328676706 */, 18 }, + /* 5030 */ { MAD_F(0x05429de2) /* 0.328763850 */, 18 }, + /* 5031 */ { MAD_F(0x0542f944) /* 0.328851001 */, 18 }, + /* 5032 */ { MAD_F(0x054354a8) /* 0.328938157 */, 18 }, + /* 5033 */ { MAD_F(0x0543b00d) /* 0.329025319 */, 18 }, + /* 5034 */ { MAD_F(0x05440b74) /* 0.329112486 */, 18 }, + /* 5035 */ { MAD_F(0x054466dd) /* 0.329199660 */, 18 }, + /* 5036 */ { MAD_F(0x0544c247) /* 0.329286839 */, 18 }, + /* 5037 */ { MAD_F(0x05451db2) /* 0.329374024 */, 18 }, + /* 5038 */ { MAD_F(0x0545791f) /* 0.329461215 */, 18 }, + /* 5039 */ { MAD_F(0x0545d48e) /* 0.329548411 */, 18 }, + + /* 5040 */ { MAD_F(0x05462ffe) /* 0.329635614 */, 18 }, + /* 5041 */ { MAD_F(0x05468b70) /* 0.329722822 */, 18 }, + /* 5042 */ { MAD_F(0x0546e6e3) /* 0.329810036 */, 18 }, + /* 5043 */ { MAD_F(0x05474258) /* 0.329897255 */, 18 }, + /* 5044 */ { MAD_F(0x05479dce) /* 0.329984481 */, 18 }, + /* 5045 */ { MAD_F(0x0547f946) /* 0.330071712 */, 18 }, + /* 5046 */ { MAD_F(0x054854c0) /* 0.330158949 */, 18 }, + /* 5047 */ { MAD_F(0x0548b03b) /* 0.330246191 */, 18 }, + /* 5048 */ { MAD_F(0x05490bb7) /* 0.330333440 */, 18 }, + /* 5049 */ { MAD_F(0x05496735) /* 0.330420694 */, 18 }, + /* 5050 */ { MAD_F(0x0549c2b5) /* 0.330507954 */, 18 }, + /* 5051 */ { MAD_F(0x054a1e36) /* 0.330595220 */, 18 }, + /* 5052 */ { MAD_F(0x054a79b9) /* 0.330682491 */, 18 }, + /* 5053 */ { MAD_F(0x054ad53d) /* 0.330769768 */, 18 }, + /* 5054 */ { MAD_F(0x054b30c3) /* 0.330857051 */, 18 }, + /* 5055 */ { MAD_F(0x054b8c4b) /* 0.330944340 */, 18 }, + + /* 5056 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 18 }, + /* 5057 */ { MAD_F(0x054c435e) /* 0.331118935 */, 18 }, + /* 5058 */ { MAD_F(0x054c9eea) /* 0.331206241 */, 18 }, + /* 5059 */ { MAD_F(0x054cfa78) /* 0.331293553 */, 18 }, + /* 5060 */ { MAD_F(0x054d5607) /* 0.331380870 */, 18 }, + /* 5061 */ { MAD_F(0x054db197) /* 0.331468193 */, 18 }, + /* 5062 */ { MAD_F(0x054e0d2a) /* 0.331555522 */, 18 }, + /* 5063 */ { MAD_F(0x054e68bd) /* 0.331642857 */, 18 }, + /* 5064 */ { MAD_F(0x054ec453) /* 0.331730198 */, 18 }, + /* 5065 */ { MAD_F(0x054f1fe9) /* 0.331817544 */, 18 }, + /* 5066 */ { MAD_F(0x054f7b82) /* 0.331904896 */, 18 }, + /* 5067 */ { MAD_F(0x054fd71c) /* 0.331992254 */, 18 }, + /* 5068 */ { MAD_F(0x055032b7) /* 0.332079617 */, 18 }, + /* 5069 */ { MAD_F(0x05508e54) /* 0.332166986 */, 18 }, + /* 5070 */ { MAD_F(0x0550e9f3) /* 0.332254361 */, 18 }, + /* 5071 */ { MAD_F(0x05514593) /* 0.332341742 */, 18 }, + + /* 5072 */ { MAD_F(0x0551a134) /* 0.332429129 */, 18 }, + /* 5073 */ { MAD_F(0x0551fcd8) /* 0.332516521 */, 18 }, + /* 5074 */ { MAD_F(0x0552587c) /* 0.332603919 */, 18 }, + /* 5075 */ { MAD_F(0x0552b423) /* 0.332691323 */, 18 }, + /* 5076 */ { MAD_F(0x05530fca) /* 0.332778732 */, 18 }, + /* 5077 */ { MAD_F(0x05536b74) /* 0.332866147 */, 18 }, + /* 5078 */ { MAD_F(0x0553c71f) /* 0.332953568 */, 18 }, + /* 5079 */ { MAD_F(0x055422cb) /* 0.333040995 */, 18 }, + /* 5080 */ { MAD_F(0x05547e79) /* 0.333128427 */, 18 }, + /* 5081 */ { MAD_F(0x0554da29) /* 0.333215865 */, 18 }, + /* 5082 */ { MAD_F(0x055535da) /* 0.333303309 */, 18 }, + /* 5083 */ { MAD_F(0x0555918c) /* 0.333390759 */, 18 }, + /* 5084 */ { MAD_F(0x0555ed40) /* 0.333478214 */, 18 }, + /* 5085 */ { MAD_F(0x055648f6) /* 0.333565675 */, 18 }, + /* 5086 */ { MAD_F(0x0556a4ad) /* 0.333653142 */, 18 }, + /* 5087 */ { MAD_F(0x05570066) /* 0.333740615 */, 18 }, + + /* 5088 */ { MAD_F(0x05575c20) /* 0.333828093 */, 18 }, + /* 5089 */ { MAD_F(0x0557b7dc) /* 0.333915577 */, 18 }, + /* 5090 */ { MAD_F(0x05581399) /* 0.334003067 */, 18 }, + /* 5091 */ { MAD_F(0x05586f58) /* 0.334090562 */, 18 }, + /* 5092 */ { MAD_F(0x0558cb19) /* 0.334178063 */, 18 }, + /* 5093 */ { MAD_F(0x055926db) /* 0.334265570 */, 18 }, + /* 5094 */ { MAD_F(0x0559829e) /* 0.334353083 */, 18 }, + /* 5095 */ { MAD_F(0x0559de63) /* 0.334440601 */, 18 }, + /* 5096 */ { MAD_F(0x055a3a2a) /* 0.334528126 */, 18 }, + /* 5097 */ { MAD_F(0x055a95f2) /* 0.334615655 */, 18 }, + /* 5098 */ { MAD_F(0x055af1bb) /* 0.334703191 */, 18 }, + /* 5099 */ { MAD_F(0x055b4d87) /* 0.334790732 */, 18 }, + /* 5100 */ { MAD_F(0x055ba953) /* 0.334878279 */, 18 }, + /* 5101 */ { MAD_F(0x055c0522) /* 0.334965832 */, 18 }, + /* 5102 */ { MAD_F(0x055c60f1) /* 0.335053391 */, 18 }, + /* 5103 */ { MAD_F(0x055cbcc3) /* 0.335140955 */, 18 }, + + /* 5104 */ { MAD_F(0x055d1896) /* 0.335228525 */, 18 }, + /* 5105 */ { MAD_F(0x055d746a) /* 0.335316100 */, 18 }, + /* 5106 */ { MAD_F(0x055dd040) /* 0.335403682 */, 18 }, + /* 5107 */ { MAD_F(0x055e2c17) /* 0.335491269 */, 18 }, + /* 5108 */ { MAD_F(0x055e87f0) /* 0.335578861 */, 18 }, + /* 5109 */ { MAD_F(0x055ee3cb) /* 0.335666460 */, 18 }, + /* 5110 */ { MAD_F(0x055f3fa7) /* 0.335754064 */, 18 }, + /* 5111 */ { MAD_F(0x055f9b85) /* 0.335841674 */, 18 }, + /* 5112 */ { MAD_F(0x055ff764) /* 0.335929290 */, 18 }, + /* 5113 */ { MAD_F(0x05605344) /* 0.336016911 */, 18 }, + /* 5114 */ { MAD_F(0x0560af27) /* 0.336104538 */, 18 }, + /* 5115 */ { MAD_F(0x05610b0a) /* 0.336192171 */, 18 }, + /* 5116 */ { MAD_F(0x056166f0) /* 0.336279809 */, 18 }, + /* 5117 */ { MAD_F(0x0561c2d7) /* 0.336367453 */, 18 }, + /* 5118 */ { MAD_F(0x05621ebf) /* 0.336455103 */, 18 }, + /* 5119 */ { MAD_F(0x05627aa9) /* 0.336542759 */, 18 }, + + /* 5120 */ { MAD_F(0x0562d694) /* 0.336630420 */, 18 }, + /* 5121 */ { MAD_F(0x05633281) /* 0.336718087 */, 18 }, + /* 5122 */ { MAD_F(0x05638e70) /* 0.336805760 */, 18 }, + /* 5123 */ { MAD_F(0x0563ea60) /* 0.336893439 */, 18 }, + /* 5124 */ { MAD_F(0x05644651) /* 0.336981123 */, 18 }, + /* 5125 */ { MAD_F(0x0564a244) /* 0.337068813 */, 18 }, + /* 5126 */ { MAD_F(0x0564fe39) /* 0.337156508 */, 18 }, + /* 5127 */ { MAD_F(0x05655a2f) /* 0.337244209 */, 18 }, + /* 5128 */ { MAD_F(0x0565b627) /* 0.337331916 */, 18 }, + /* 5129 */ { MAD_F(0x05661220) /* 0.337419629 */, 18 }, + /* 5130 */ { MAD_F(0x05666e1a) /* 0.337507347 */, 18 }, + /* 5131 */ { MAD_F(0x0566ca17) /* 0.337595071 */, 18 }, + /* 5132 */ { MAD_F(0x05672614) /* 0.337682801 */, 18 }, + /* 5133 */ { MAD_F(0x05678214) /* 0.337770537 */, 18 }, + /* 5134 */ { MAD_F(0x0567de15) /* 0.337858278 */, 18 }, + /* 5135 */ { MAD_F(0x05683a17) /* 0.337946025 */, 18 }, + + /* 5136 */ { MAD_F(0x0568961b) /* 0.338033777 */, 18 }, + /* 5137 */ { MAD_F(0x0568f220) /* 0.338121535 */, 18 }, + /* 5138 */ { MAD_F(0x05694e27) /* 0.338209299 */, 18 }, + /* 5139 */ { MAD_F(0x0569aa30) /* 0.338297069 */, 18 }, + /* 5140 */ { MAD_F(0x056a063a) /* 0.338384844 */, 18 }, + /* 5141 */ { MAD_F(0x056a6245) /* 0.338472625 */, 18 }, + /* 5142 */ { MAD_F(0x056abe52) /* 0.338560412 */, 18 }, + /* 5143 */ { MAD_F(0x056b1a61) /* 0.338648204 */, 18 }, + /* 5144 */ { MAD_F(0x056b7671) /* 0.338736002 */, 18 }, + /* 5145 */ { MAD_F(0x056bd283) /* 0.338823806 */, 18 }, + /* 5146 */ { MAD_F(0x056c2e96) /* 0.338911616 */, 18 }, + /* 5147 */ { MAD_F(0x056c8aab) /* 0.338999431 */, 18 }, + /* 5148 */ { MAD_F(0x056ce6c1) /* 0.339087252 */, 18 }, + /* 5149 */ { MAD_F(0x056d42d9) /* 0.339175078 */, 18 }, + /* 5150 */ { MAD_F(0x056d9ef2) /* 0.339262910 */, 18 }, + /* 5151 */ { MAD_F(0x056dfb0d) /* 0.339350748 */, 18 }, + + /* 5152 */ { MAD_F(0x056e5729) /* 0.339438592 */, 18 }, + /* 5153 */ { MAD_F(0x056eb347) /* 0.339526441 */, 18 }, + /* 5154 */ { MAD_F(0x056f0f66) /* 0.339614296 */, 18 }, + /* 5155 */ { MAD_F(0x056f6b87) /* 0.339702157 */, 18 }, + /* 5156 */ { MAD_F(0x056fc7aa) /* 0.339790023 */, 18 }, + /* 5157 */ { MAD_F(0x057023cd) /* 0.339877895 */, 18 }, + /* 5158 */ { MAD_F(0x05707ff3) /* 0.339965773 */, 18 }, + /* 5159 */ { MAD_F(0x0570dc1a) /* 0.340053656 */, 18 }, + /* 5160 */ { MAD_F(0x05713843) /* 0.340141545 */, 18 }, + /* 5161 */ { MAD_F(0x0571946d) /* 0.340229440 */, 18 }, + /* 5162 */ { MAD_F(0x0571f098) /* 0.340317340 */, 18 }, + /* 5163 */ { MAD_F(0x05724cc5) /* 0.340405246 */, 18 }, + /* 5164 */ { MAD_F(0x0572a8f4) /* 0.340493158 */, 18 }, + /* 5165 */ { MAD_F(0x05730524) /* 0.340581075 */, 18 }, + /* 5166 */ { MAD_F(0x05736156) /* 0.340668999 */, 18 }, + /* 5167 */ { MAD_F(0x0573bd89) /* 0.340756927 */, 18 }, + + /* 5168 */ { MAD_F(0x057419be) /* 0.340844862 */, 18 }, + /* 5169 */ { MAD_F(0x057475f4) /* 0.340932802 */, 18 }, + /* 5170 */ { MAD_F(0x0574d22c) /* 0.341020748 */, 18 }, + /* 5171 */ { MAD_F(0x05752e65) /* 0.341108699 */, 18 }, + /* 5172 */ { MAD_F(0x05758aa0) /* 0.341196656 */, 18 }, + /* 5173 */ { MAD_F(0x0575e6dc) /* 0.341284619 */, 18 }, + /* 5174 */ { MAD_F(0x0576431a) /* 0.341372587 */, 18 }, + /* 5175 */ { MAD_F(0x05769f59) /* 0.341460562 */, 18 }, + /* 5176 */ { MAD_F(0x0576fb9a) /* 0.341548541 */, 18 }, + /* 5177 */ { MAD_F(0x057757dd) /* 0.341636527 */, 18 }, + /* 5178 */ { MAD_F(0x0577b421) /* 0.341724518 */, 18 }, + /* 5179 */ { MAD_F(0x05781066) /* 0.341812515 */, 18 }, + /* 5180 */ { MAD_F(0x05786cad) /* 0.341900517 */, 18 }, + /* 5181 */ { MAD_F(0x0578c8f5) /* 0.341988525 */, 18 }, + /* 5182 */ { MAD_F(0x0579253f) /* 0.342076539 */, 18 }, + /* 5183 */ { MAD_F(0x0579818b) /* 0.342164558 */, 18 }, + + /* 5184 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 18 }, + /* 5185 */ { MAD_F(0x057a3a27) /* 0.342340614 */, 18 }, + /* 5186 */ { MAD_F(0x057a9677) /* 0.342428651 */, 18 }, + /* 5187 */ { MAD_F(0x057af2c8) /* 0.342516693 */, 18 }, + /* 5188 */ { MAD_F(0x057b4f1c) /* 0.342604741 */, 18 }, + /* 5189 */ { MAD_F(0x057bab70) /* 0.342692794 */, 18 }, + /* 5190 */ { MAD_F(0x057c07c6) /* 0.342780853 */, 18 }, + /* 5191 */ { MAD_F(0x057c641e) /* 0.342868918 */, 18 }, + /* 5192 */ { MAD_F(0x057cc077) /* 0.342956988 */, 18 }, + /* 5193 */ { MAD_F(0x057d1cd2) /* 0.343045064 */, 18 }, + /* 5194 */ { MAD_F(0x057d792e) /* 0.343133146 */, 18 }, + /* 5195 */ { MAD_F(0x057dd58c) /* 0.343221233 */, 18 }, + /* 5196 */ { MAD_F(0x057e31eb) /* 0.343309326 */, 18 }, + /* 5197 */ { MAD_F(0x057e8e4c) /* 0.343397425 */, 18 }, + /* 5198 */ { MAD_F(0x057eeaae) /* 0.343485529 */, 18 }, + /* 5199 */ { MAD_F(0x057f4712) /* 0.343573639 */, 18 }, + + /* 5200 */ { MAD_F(0x057fa378) /* 0.343661754 */, 18 }, + /* 5201 */ { MAD_F(0x057fffde) /* 0.343749876 */, 18 }, + /* 5202 */ { MAD_F(0x05805c47) /* 0.343838003 */, 18 }, + /* 5203 */ { MAD_F(0x0580b8b1) /* 0.343926135 */, 18 }, + /* 5204 */ { MAD_F(0x0581151c) /* 0.344014273 */, 18 }, + /* 5205 */ { MAD_F(0x05817189) /* 0.344102417 */, 18 }, + /* 5206 */ { MAD_F(0x0581cdf7) /* 0.344190566 */, 18 }, + /* 5207 */ { MAD_F(0x05822a67) /* 0.344278722 */, 18 }, + /* 5208 */ { MAD_F(0x058286d9) /* 0.344366882 */, 18 }, + /* 5209 */ { MAD_F(0x0582e34c) /* 0.344455049 */, 18 }, + /* 5210 */ { MAD_F(0x05833fc0) /* 0.344543221 */, 18 }, + /* 5211 */ { MAD_F(0x05839c36) /* 0.344631398 */, 18 }, + /* 5212 */ { MAD_F(0x0583f8ae) /* 0.344719582 */, 18 }, + /* 5213 */ { MAD_F(0x05845527) /* 0.344807771 */, 18 }, + /* 5214 */ { MAD_F(0x0584b1a1) /* 0.344895965 */, 18 }, + /* 5215 */ { MAD_F(0x05850e1e) /* 0.344984165 */, 18 }, + + /* 5216 */ { MAD_F(0x05856a9b) /* 0.345072371 */, 18 }, + /* 5217 */ { MAD_F(0x0585c71a) /* 0.345160583 */, 18 }, + /* 5218 */ { MAD_F(0x0586239b) /* 0.345248800 */, 18 }, + /* 5219 */ { MAD_F(0x0586801d) /* 0.345337023 */, 18 }, + /* 5220 */ { MAD_F(0x0586dca1) /* 0.345425251 */, 18 }, + /* 5221 */ { MAD_F(0x05873926) /* 0.345513485 */, 18 }, + /* 5222 */ { MAD_F(0x058795ac) /* 0.345601725 */, 18 }, + /* 5223 */ { MAD_F(0x0587f235) /* 0.345689970 */, 18 }, + /* 5224 */ { MAD_F(0x05884ebe) /* 0.345778221 */, 18 }, + /* 5225 */ { MAD_F(0x0588ab49) /* 0.345866478 */, 18 }, + /* 5226 */ { MAD_F(0x058907d6) /* 0.345954740 */, 18 }, + /* 5227 */ { MAD_F(0x05896464) /* 0.346043008 */, 18 }, + /* 5228 */ { MAD_F(0x0589c0f4) /* 0.346131281 */, 18 }, + /* 5229 */ { MAD_F(0x058a1d85) /* 0.346219560 */, 18 }, + /* 5230 */ { MAD_F(0x058a7a18) /* 0.346307845 */, 18 }, + /* 5231 */ { MAD_F(0x058ad6ac) /* 0.346396135 */, 18 }, + + /* 5232 */ { MAD_F(0x058b3342) /* 0.346484431 */, 18 }, + /* 5233 */ { MAD_F(0x058b8fd9) /* 0.346572733 */, 18 }, + /* 5234 */ { MAD_F(0x058bec72) /* 0.346661040 */, 18 }, + /* 5235 */ { MAD_F(0x058c490c) /* 0.346749353 */, 18 }, + /* 5236 */ { MAD_F(0x058ca5a8) /* 0.346837671 */, 18 }, + /* 5237 */ { MAD_F(0x058d0246) /* 0.346925996 */, 18 }, + /* 5238 */ { MAD_F(0x058d5ee4) /* 0.347014325 */, 18 }, + /* 5239 */ { MAD_F(0x058dbb85) /* 0.347102661 */, 18 }, + /* 5240 */ { MAD_F(0x058e1827) /* 0.347191002 */, 18 }, + /* 5241 */ { MAD_F(0x058e74ca) /* 0.347279348 */, 18 }, + /* 5242 */ { MAD_F(0x058ed16f) /* 0.347367700 */, 18 }, + /* 5243 */ { MAD_F(0x058f2e15) /* 0.347456058 */, 18 }, + /* 5244 */ { MAD_F(0x058f8abd) /* 0.347544422 */, 18 }, + /* 5245 */ { MAD_F(0x058fe766) /* 0.347632791 */, 18 }, + /* 5246 */ { MAD_F(0x05904411) /* 0.347721165 */, 18 }, + /* 5247 */ { MAD_F(0x0590a0be) /* 0.347809546 */, 18 }, + + /* 5248 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 18 }, + /* 5249 */ { MAD_F(0x05915a1b) /* 0.347986323 */, 18 }, + /* 5250 */ { MAD_F(0x0591b6cc) /* 0.348074720 */, 18 }, + /* 5251 */ { MAD_F(0x0592137e) /* 0.348163123 */, 18 }, + /* 5252 */ { MAD_F(0x05927032) /* 0.348251531 */, 18 }, + /* 5253 */ { MAD_F(0x0592cce8) /* 0.348339945 */, 18 }, + /* 5254 */ { MAD_F(0x0593299f) /* 0.348428365 */, 18 }, + /* 5255 */ { MAD_F(0x05938657) /* 0.348516790 */, 18 }, + /* 5256 */ { MAD_F(0x0593e311) /* 0.348605221 */, 18 }, + /* 5257 */ { MAD_F(0x05943fcd) /* 0.348693657 */, 18 }, + /* 5258 */ { MAD_F(0x05949c8a) /* 0.348782099 */, 18 }, + /* 5259 */ { MAD_F(0x0594f948) /* 0.348870547 */, 18 }, + /* 5260 */ { MAD_F(0x05955608) /* 0.348959000 */, 18 }, + /* 5261 */ { MAD_F(0x0595b2ca) /* 0.349047459 */, 18 }, + /* 5262 */ { MAD_F(0x05960f8c) /* 0.349135923 */, 18 }, + /* 5263 */ { MAD_F(0x05966c51) /* 0.349224393 */, 18 }, + + /* 5264 */ { MAD_F(0x0596c917) /* 0.349312869 */, 18 }, + /* 5265 */ { MAD_F(0x059725de) /* 0.349401350 */, 18 }, + /* 5266 */ { MAD_F(0x059782a7) /* 0.349489837 */, 18 }, + /* 5267 */ { MAD_F(0x0597df72) /* 0.349578329 */, 18 }, + /* 5268 */ { MAD_F(0x05983c3e) /* 0.349666827 */, 18 }, + /* 5269 */ { MAD_F(0x0598990c) /* 0.349755331 */, 18 }, + /* 5270 */ { MAD_F(0x0598f5db) /* 0.349843840 */, 18 }, + /* 5271 */ { MAD_F(0x059952ab) /* 0.349932355 */, 18 }, + /* 5272 */ { MAD_F(0x0599af7d) /* 0.350020876 */, 18 }, + /* 5273 */ { MAD_F(0x059a0c51) /* 0.350109402 */, 18 }, + /* 5274 */ { MAD_F(0x059a6926) /* 0.350197933 */, 18 }, + /* 5275 */ { MAD_F(0x059ac5fc) /* 0.350286470 */, 18 }, + /* 5276 */ { MAD_F(0x059b22d4) /* 0.350375013 */, 18 }, + /* 5277 */ { MAD_F(0x059b7fae) /* 0.350463562 */, 18 }, + /* 5278 */ { MAD_F(0x059bdc89) /* 0.350552116 */, 18 }, + /* 5279 */ { MAD_F(0x059c3965) /* 0.350640675 */, 18 }, + + /* 5280 */ { MAD_F(0x059c9643) /* 0.350729240 */, 18 }, + /* 5281 */ { MAD_F(0x059cf323) /* 0.350817811 */, 18 }, + /* 5282 */ { MAD_F(0x059d5004) /* 0.350906388 */, 18 }, + /* 5283 */ { MAD_F(0x059dace6) /* 0.350994970 */, 18 }, + /* 5284 */ { MAD_F(0x059e09cb) /* 0.351083557 */, 18 }, + /* 5285 */ { MAD_F(0x059e66b0) /* 0.351172150 */, 18 }, + /* 5286 */ { MAD_F(0x059ec397) /* 0.351260749 */, 18 }, + /* 5287 */ { MAD_F(0x059f2080) /* 0.351349353 */, 18 }, + /* 5288 */ { MAD_F(0x059f7d6a) /* 0.351437963 */, 18 }, + /* 5289 */ { MAD_F(0x059fda55) /* 0.351526579 */, 18 }, + /* 5290 */ { MAD_F(0x05a03742) /* 0.351615200 */, 18 }, + /* 5291 */ { MAD_F(0x05a09431) /* 0.351703827 */, 18 }, + /* 5292 */ { MAD_F(0x05a0f121) /* 0.351792459 */, 18 }, + /* 5293 */ { MAD_F(0x05a14e12) /* 0.351881097 */, 18 }, + /* 5294 */ { MAD_F(0x05a1ab05) /* 0.351969740 */, 18 }, + /* 5295 */ { MAD_F(0x05a207fa) /* 0.352058389 */, 18 }, + + /* 5296 */ { MAD_F(0x05a264f0) /* 0.352147044 */, 18 }, + /* 5297 */ { MAD_F(0x05a2c1e7) /* 0.352235704 */, 18 }, + /* 5298 */ { MAD_F(0x05a31ee1) /* 0.352324369 */, 18 }, + /* 5299 */ { MAD_F(0x05a37bdb) /* 0.352413041 */, 18 }, + /* 5300 */ { MAD_F(0x05a3d8d7) /* 0.352501718 */, 18 }, + /* 5301 */ { MAD_F(0x05a435d5) /* 0.352590400 */, 18 }, + /* 5302 */ { MAD_F(0x05a492d4) /* 0.352679088 */, 18 }, + /* 5303 */ { MAD_F(0x05a4efd4) /* 0.352767782 */, 18 }, + /* 5304 */ { MAD_F(0x05a54cd6) /* 0.352856481 */, 18 }, + /* 5305 */ { MAD_F(0x05a5a9da) /* 0.352945186 */, 18 }, + /* 5306 */ { MAD_F(0x05a606df) /* 0.353033896 */, 18 }, + /* 5307 */ { MAD_F(0x05a663e5) /* 0.353122612 */, 18 }, + /* 5308 */ { MAD_F(0x05a6c0ed) /* 0.353211333 */, 18 }, + /* 5309 */ { MAD_F(0x05a71df7) /* 0.353300061 */, 18 }, + /* 5310 */ { MAD_F(0x05a77b02) /* 0.353388793 */, 18 }, + /* 5311 */ { MAD_F(0x05a7d80e) /* 0.353477531 */, 18 }, + + /* 5312 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 18 }, + /* 5313 */ { MAD_F(0x05a8922c) /* 0.353655024 */, 18 }, + /* 5314 */ { MAD_F(0x05a8ef3c) /* 0.353743779 */, 18 }, + /* 5315 */ { MAD_F(0x05a94c4f) /* 0.353832540 */, 18 }, + /* 5316 */ { MAD_F(0x05a9a963) /* 0.353921306 */, 18 }, + /* 5317 */ { MAD_F(0x05aa0678) /* 0.354010077 */, 18 }, + /* 5318 */ { MAD_F(0x05aa638f) /* 0.354098855 */, 18 }, + /* 5319 */ { MAD_F(0x05aac0a8) /* 0.354187637 */, 18 }, + /* 5320 */ { MAD_F(0x05ab1dc2) /* 0.354276426 */, 18 }, + /* 5321 */ { MAD_F(0x05ab7add) /* 0.354365220 */, 18 }, + /* 5322 */ { MAD_F(0x05abd7fa) /* 0.354454019 */, 18 }, + /* 5323 */ { MAD_F(0x05ac3518) /* 0.354542824 */, 18 }, + /* 5324 */ { MAD_F(0x05ac9238) /* 0.354631635 */, 18 }, + /* 5325 */ { MAD_F(0x05acef5a) /* 0.354720451 */, 18 }, + /* 5326 */ { MAD_F(0x05ad4c7d) /* 0.354809272 */, 18 }, + /* 5327 */ { MAD_F(0x05ada9a1) /* 0.354898100 */, 18 }, + + /* 5328 */ { MAD_F(0x05ae06c7) /* 0.354986932 */, 18 }, + /* 5329 */ { MAD_F(0x05ae63ee) /* 0.355075771 */, 18 }, + /* 5330 */ { MAD_F(0x05aec117) /* 0.355164615 */, 18 }, + /* 5331 */ { MAD_F(0x05af1e41) /* 0.355253464 */, 18 }, + /* 5332 */ { MAD_F(0x05af7b6d) /* 0.355342319 */, 18 }, + /* 5333 */ { MAD_F(0x05afd89b) /* 0.355431180 */, 18 }, + /* 5334 */ { MAD_F(0x05b035c9) /* 0.355520046 */, 18 }, + /* 5335 */ { MAD_F(0x05b092fa) /* 0.355608917 */, 18 }, + /* 5336 */ { MAD_F(0x05b0f02b) /* 0.355697795 */, 18 }, + /* 5337 */ { MAD_F(0x05b14d5f) /* 0.355786677 */, 18 }, + /* 5338 */ { MAD_F(0x05b1aa94) /* 0.355875566 */, 18 }, + /* 5339 */ { MAD_F(0x05b207ca) /* 0.355964460 */, 18 }, + /* 5340 */ { MAD_F(0x05b26502) /* 0.356053359 */, 18 }, + /* 5341 */ { MAD_F(0x05b2c23b) /* 0.356142264 */, 18 }, + /* 5342 */ { MAD_F(0x05b31f76) /* 0.356231175 */, 18 }, + /* 5343 */ { MAD_F(0x05b37cb2) /* 0.356320091 */, 18 }, + + /* 5344 */ { MAD_F(0x05b3d9f0) /* 0.356409012 */, 18 }, + /* 5345 */ { MAD_F(0x05b4372f) /* 0.356497940 */, 18 }, + /* 5346 */ { MAD_F(0x05b4946f) /* 0.356586872 */, 18 }, + /* 5347 */ { MAD_F(0x05b4f1b2) /* 0.356675811 */, 18 }, + /* 5348 */ { MAD_F(0x05b54ef5) /* 0.356764754 */, 18 }, + /* 5349 */ { MAD_F(0x05b5ac3a) /* 0.356853704 */, 18 }, + /* 5350 */ { MAD_F(0x05b60981) /* 0.356942659 */, 18 }, + /* 5351 */ { MAD_F(0x05b666c9) /* 0.357031619 */, 18 }, + /* 5352 */ { MAD_F(0x05b6c413) /* 0.357120585 */, 18 }, + /* 5353 */ { MAD_F(0x05b7215e) /* 0.357209557 */, 18 }, + /* 5354 */ { MAD_F(0x05b77eab) /* 0.357298534 */, 18 }, + /* 5355 */ { MAD_F(0x05b7dbf9) /* 0.357387516 */, 18 }, + /* 5356 */ { MAD_F(0x05b83948) /* 0.357476504 */, 18 }, + /* 5357 */ { MAD_F(0x05b89699) /* 0.357565498 */, 18 }, + /* 5358 */ { MAD_F(0x05b8f3ec) /* 0.357654497 */, 18 }, + /* 5359 */ { MAD_F(0x05b95140) /* 0.357743502 */, 18 }, + + /* 5360 */ { MAD_F(0x05b9ae95) /* 0.357832512 */, 18 }, + /* 5361 */ { MAD_F(0x05ba0bec) /* 0.357921528 */, 18 }, + /* 5362 */ { MAD_F(0x05ba6945) /* 0.358010550 */, 18 }, + /* 5363 */ { MAD_F(0x05bac69f) /* 0.358099576 */, 18 }, + /* 5364 */ { MAD_F(0x05bb23fa) /* 0.358188609 */, 18 }, + /* 5365 */ { MAD_F(0x05bb8157) /* 0.358277647 */, 18 }, + /* 5366 */ { MAD_F(0x05bbdeb6) /* 0.358366690 */, 18 }, + /* 5367 */ { MAD_F(0x05bc3c16) /* 0.358455739 */, 18 }, + /* 5368 */ { MAD_F(0x05bc9977) /* 0.358544794 */, 18 }, + /* 5369 */ { MAD_F(0x05bcf6da) /* 0.358633854 */, 18 }, + /* 5370 */ { MAD_F(0x05bd543e) /* 0.358722920 */, 18 }, + /* 5371 */ { MAD_F(0x05bdb1a4) /* 0.358811991 */, 18 }, + /* 5372 */ { MAD_F(0x05be0f0b) /* 0.358901067 */, 18 }, + /* 5373 */ { MAD_F(0x05be6c74) /* 0.358990150 */, 18 }, + /* 5374 */ { MAD_F(0x05bec9df) /* 0.359079237 */, 18 }, + /* 5375 */ { MAD_F(0x05bf274a) /* 0.359168331 */, 18 }, + + /* 5376 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 18 }, + /* 5377 */ { MAD_F(0x05bfe226) /* 0.359346534 */, 18 }, + /* 5378 */ { MAD_F(0x05c03f97) /* 0.359435644 */, 18 }, + /* 5379 */ { MAD_F(0x05c09d08) /* 0.359524759 */, 18 }, + /* 5380 */ { MAD_F(0x05c0fa7c) /* 0.359613880 */, 18 }, + /* 5381 */ { MAD_F(0x05c157f0) /* 0.359703006 */, 18 }, + /* 5382 */ { MAD_F(0x05c1b566) /* 0.359792138 */, 18 }, + /* 5383 */ { MAD_F(0x05c212de) /* 0.359881276 */, 18 }, + /* 5384 */ { MAD_F(0x05c27057) /* 0.359970419 */, 18 }, + /* 5385 */ { MAD_F(0x05c2cdd2) /* 0.360059567 */, 18 }, + /* 5386 */ { MAD_F(0x05c32b4e) /* 0.360148721 */, 18 }, + /* 5387 */ { MAD_F(0x05c388cb) /* 0.360237881 */, 18 }, + /* 5388 */ { MAD_F(0x05c3e64b) /* 0.360327046 */, 18 }, + /* 5389 */ { MAD_F(0x05c443cb) /* 0.360416216 */, 18 }, + /* 5390 */ { MAD_F(0x05c4a14d) /* 0.360505392 */, 18 }, + /* 5391 */ { MAD_F(0x05c4fed1) /* 0.360594574 */, 18 }, + + /* 5392 */ { MAD_F(0x05c55c56) /* 0.360683761 */, 18 }, + /* 5393 */ { MAD_F(0x05c5b9dc) /* 0.360772953 */, 18 }, + /* 5394 */ { MAD_F(0x05c61764) /* 0.360862152 */, 18 }, + /* 5395 */ { MAD_F(0x05c674ed) /* 0.360951355 */, 18 }, + /* 5396 */ { MAD_F(0x05c6d278) /* 0.361040564 */, 18 }, + /* 5397 */ { MAD_F(0x05c73005) /* 0.361129779 */, 18 }, + /* 5398 */ { MAD_F(0x05c78d93) /* 0.361218999 */, 18 }, + /* 5399 */ { MAD_F(0x05c7eb22) /* 0.361308225 */, 18 }, + /* 5400 */ { MAD_F(0x05c848b3) /* 0.361397456 */, 18 }, + /* 5401 */ { MAD_F(0x05c8a645) /* 0.361486693 */, 18 }, + /* 5402 */ { MAD_F(0x05c903d9) /* 0.361575935 */, 18 }, + /* 5403 */ { MAD_F(0x05c9616e) /* 0.361665183 */, 18 }, + /* 5404 */ { MAD_F(0x05c9bf05) /* 0.361754436 */, 18 }, + /* 5405 */ { MAD_F(0x05ca1c9d) /* 0.361843695 */, 18 }, + /* 5406 */ { MAD_F(0x05ca7a37) /* 0.361932959 */, 18 }, + /* 5407 */ { MAD_F(0x05cad7d2) /* 0.362022229 */, 18 }, + + /* 5408 */ { MAD_F(0x05cb356e) /* 0.362111504 */, 18 }, + /* 5409 */ { MAD_F(0x05cb930d) /* 0.362200785 */, 18 }, + /* 5410 */ { MAD_F(0x05cbf0ac) /* 0.362290071 */, 18 }, + /* 5411 */ { MAD_F(0x05cc4e4d) /* 0.362379362 */, 18 }, + /* 5412 */ { MAD_F(0x05ccabf0) /* 0.362468660 */, 18 }, + /* 5413 */ { MAD_F(0x05cd0994) /* 0.362557962 */, 18 }, + /* 5414 */ { MAD_F(0x05cd6739) /* 0.362647271 */, 18 }, + /* 5415 */ { MAD_F(0x05cdc4e0) /* 0.362736584 */, 18 }, + /* 5416 */ { MAD_F(0x05ce2289) /* 0.362825904 */, 18 }, + /* 5417 */ { MAD_F(0x05ce8033) /* 0.362915228 */, 18 }, + /* 5418 */ { MAD_F(0x05ceddde) /* 0.363004559 */, 18 }, + /* 5419 */ { MAD_F(0x05cf3b8b) /* 0.363093894 */, 18 }, + /* 5420 */ { MAD_F(0x05cf9939) /* 0.363183236 */, 18 }, + /* 5421 */ { MAD_F(0x05cff6e9) /* 0.363272582 */, 18 }, + /* 5422 */ { MAD_F(0x05d0549a) /* 0.363361935 */, 18 }, + /* 5423 */ { MAD_F(0x05d0b24d) /* 0.363451292 */, 18 }, + + /* 5424 */ { MAD_F(0x05d11001) /* 0.363540655 */, 18 }, + /* 5425 */ { MAD_F(0x05d16db7) /* 0.363630024 */, 18 }, + /* 5426 */ { MAD_F(0x05d1cb6e) /* 0.363719398 */, 18 }, + /* 5427 */ { MAD_F(0x05d22927) /* 0.363808778 */, 18 }, + /* 5428 */ { MAD_F(0x05d286e1) /* 0.363898163 */, 18 }, + /* 5429 */ { MAD_F(0x05d2e49d) /* 0.363987554 */, 18 }, + /* 5430 */ { MAD_F(0x05d3425a) /* 0.364076950 */, 18 }, + /* 5431 */ { MAD_F(0x05d3a018) /* 0.364166352 */, 18 }, + /* 5432 */ { MAD_F(0x05d3fdd8) /* 0.364255759 */, 18 }, + /* 5433 */ { MAD_F(0x05d45b9a) /* 0.364345171 */, 18 }, + /* 5434 */ { MAD_F(0x05d4b95d) /* 0.364434589 */, 18 }, + /* 5435 */ { MAD_F(0x05d51721) /* 0.364524013 */, 18 }, + /* 5436 */ { MAD_F(0x05d574e7) /* 0.364613442 */, 18 }, + /* 5437 */ { MAD_F(0x05d5d2af) /* 0.364702877 */, 18 }, + /* 5438 */ { MAD_F(0x05d63078) /* 0.364792317 */, 18 }, + /* 5439 */ { MAD_F(0x05d68e42) /* 0.364881762 */, 18 }, + + /* 5440 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 18 }, + /* 5441 */ { MAD_F(0x05d749db) /* 0.365060669 */, 18 }, + /* 5442 */ { MAD_F(0x05d7a7aa) /* 0.365150131 */, 18 }, + /* 5443 */ { MAD_F(0x05d8057a) /* 0.365239599 */, 18 }, + /* 5444 */ { MAD_F(0x05d8634c) /* 0.365329072 */, 18 }, + /* 5445 */ { MAD_F(0x05d8c11f) /* 0.365418550 */, 18 }, + /* 5446 */ { MAD_F(0x05d91ef4) /* 0.365508034 */, 18 }, + /* 5447 */ { MAD_F(0x05d97cca) /* 0.365597523 */, 18 }, + /* 5448 */ { MAD_F(0x05d9daa1) /* 0.365687018 */, 18 }, + /* 5449 */ { MAD_F(0x05da387a) /* 0.365776518 */, 18 }, + /* 5450 */ { MAD_F(0x05da9655) /* 0.365866024 */, 18 }, + /* 5451 */ { MAD_F(0x05daf431) /* 0.365955536 */, 18 }, + /* 5452 */ { MAD_F(0x05db520e) /* 0.366045052 */, 18 }, + /* 5453 */ { MAD_F(0x05dbafed) /* 0.366134574 */, 18 }, + /* 5454 */ { MAD_F(0x05dc0dce) /* 0.366224102 */, 18 }, + /* 5455 */ { MAD_F(0x05dc6baf) /* 0.366313635 */, 18 }, + + /* 5456 */ { MAD_F(0x05dcc993) /* 0.366403174 */, 18 }, + /* 5457 */ { MAD_F(0x05dd2778) /* 0.366492718 */, 18 }, + /* 5458 */ { MAD_F(0x05dd855e) /* 0.366582267 */, 18 }, + /* 5459 */ { MAD_F(0x05dde346) /* 0.366671822 */, 18 }, + /* 5460 */ { MAD_F(0x05de412f) /* 0.366761383 */, 18 }, + /* 5461 */ { MAD_F(0x05de9f1a) /* 0.366850949 */, 18 }, + /* 5462 */ { MAD_F(0x05defd06) /* 0.366940520 */, 18 }, + /* 5463 */ { MAD_F(0x05df5af3) /* 0.367030097 */, 18 }, + /* 5464 */ { MAD_F(0x05dfb8e2) /* 0.367119680 */, 18 }, + /* 5465 */ { MAD_F(0x05e016d3) /* 0.367209267 */, 18 }, + /* 5466 */ { MAD_F(0x05e074c5) /* 0.367298861 */, 18 }, + /* 5467 */ { MAD_F(0x05e0d2b8) /* 0.367388459 */, 18 }, + /* 5468 */ { MAD_F(0x05e130ad) /* 0.367478064 */, 18 }, + /* 5469 */ { MAD_F(0x05e18ea4) /* 0.367567673 */, 18 }, + /* 5470 */ { MAD_F(0x05e1ec9c) /* 0.367657288 */, 18 }, + /* 5471 */ { MAD_F(0x05e24a95) /* 0.367746909 */, 18 }, + + /* 5472 */ { MAD_F(0x05e2a890) /* 0.367836535 */, 18 }, + /* 5473 */ { MAD_F(0x05e3068c) /* 0.367926167 */, 18 }, + /* 5474 */ { MAD_F(0x05e3648a) /* 0.368015804 */, 18 }, + /* 5475 */ { MAD_F(0x05e3c289) /* 0.368105446 */, 18 }, + /* 5476 */ { MAD_F(0x05e4208a) /* 0.368195094 */, 18 }, + /* 5477 */ { MAD_F(0x05e47e8c) /* 0.368284747 */, 18 }, + /* 5478 */ { MAD_F(0x05e4dc8f) /* 0.368374406 */, 18 }, + /* 5479 */ { MAD_F(0x05e53a94) /* 0.368464070 */, 18 }, + /* 5480 */ { MAD_F(0x05e5989b) /* 0.368553740 */, 18 }, + /* 5481 */ { MAD_F(0x05e5f6a3) /* 0.368643415 */, 18 }, + /* 5482 */ { MAD_F(0x05e654ac) /* 0.368733096 */, 18 }, + /* 5483 */ { MAD_F(0x05e6b2b7) /* 0.368822782 */, 18 }, + /* 5484 */ { MAD_F(0x05e710c4) /* 0.368912473 */, 18 }, + /* 5485 */ { MAD_F(0x05e76ed2) /* 0.369002170 */, 18 }, + /* 5486 */ { MAD_F(0x05e7cce1) /* 0.369091873 */, 18 }, + /* 5487 */ { MAD_F(0x05e82af2) /* 0.369181581 */, 18 }, + + /* 5488 */ { MAD_F(0x05e88904) /* 0.369271294 */, 18 }, + /* 5489 */ { MAD_F(0x05e8e718) /* 0.369361013 */, 18 }, + /* 5490 */ { MAD_F(0x05e9452d) /* 0.369450737 */, 18 }, + /* 5491 */ { MAD_F(0x05e9a343) /* 0.369540467 */, 18 }, + /* 5492 */ { MAD_F(0x05ea015c) /* 0.369630202 */, 18 }, + /* 5493 */ { MAD_F(0x05ea5f75) /* 0.369719942 */, 18 }, + /* 5494 */ { MAD_F(0x05eabd90) /* 0.369809688 */, 18 }, + /* 5495 */ { MAD_F(0x05eb1bad) /* 0.369899440 */, 18 }, + /* 5496 */ { MAD_F(0x05eb79cb) /* 0.369989197 */, 18 }, + /* 5497 */ { MAD_F(0x05ebd7ea) /* 0.370078959 */, 18 }, + /* 5498 */ { MAD_F(0x05ec360b) /* 0.370168727 */, 18 }, + /* 5499 */ { MAD_F(0x05ec942d) /* 0.370258500 */, 18 }, + /* 5500 */ { MAD_F(0x05ecf251) /* 0.370348279 */, 18 }, + /* 5501 */ { MAD_F(0x05ed5076) /* 0.370438063 */, 18 }, + /* 5502 */ { MAD_F(0x05edae9d) /* 0.370527853 */, 18 }, + /* 5503 */ { MAD_F(0x05ee0cc5) /* 0.370617648 */, 18 }, + + /* 5504 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 18 }, + /* 5505 */ { MAD_F(0x05eec91a) /* 0.370797254 */, 18 }, + /* 5506 */ { MAD_F(0x05ef2746) /* 0.370887065 */, 18 }, + /* 5507 */ { MAD_F(0x05ef8574) /* 0.370976882 */, 18 }, + /* 5508 */ { MAD_F(0x05efe3a4) /* 0.371066704 */, 18 }, + /* 5509 */ { MAD_F(0x05f041d5) /* 0.371156532 */, 18 }, + /* 5510 */ { MAD_F(0x05f0a007) /* 0.371246365 */, 18 }, + /* 5511 */ { MAD_F(0x05f0fe3b) /* 0.371336203 */, 18 }, + /* 5512 */ { MAD_F(0x05f15c70) /* 0.371426047 */, 18 }, + /* 5513 */ { MAD_F(0x05f1baa7) /* 0.371515897 */, 18 }, + /* 5514 */ { MAD_F(0x05f218df) /* 0.371605751 */, 18 }, + /* 5515 */ { MAD_F(0x05f27719) /* 0.371695612 */, 18 }, + /* 5516 */ { MAD_F(0x05f2d554) /* 0.371785477 */, 18 }, + /* 5517 */ { MAD_F(0x05f33390) /* 0.371875348 */, 18 }, + /* 5518 */ { MAD_F(0x05f391cf) /* 0.371965225 */, 18 }, + /* 5519 */ { MAD_F(0x05f3f00e) /* 0.372055107 */, 18 }, + + /* 5520 */ { MAD_F(0x05f44e4f) /* 0.372144994 */, 18 }, + /* 5521 */ { MAD_F(0x05f4ac91) /* 0.372234887 */, 18 }, + /* 5522 */ { MAD_F(0x05f50ad5) /* 0.372324785 */, 18 }, + /* 5523 */ { MAD_F(0x05f5691b) /* 0.372414689 */, 18 }, + /* 5524 */ { MAD_F(0x05f5c761) /* 0.372504598 */, 18 }, + /* 5525 */ { MAD_F(0x05f625aa) /* 0.372594513 */, 18 }, + /* 5526 */ { MAD_F(0x05f683f3) /* 0.372684433 */, 18 }, + /* 5527 */ { MAD_F(0x05f6e23f) /* 0.372774358 */, 18 }, + /* 5528 */ { MAD_F(0x05f7408b) /* 0.372864289 */, 18 }, + /* 5529 */ { MAD_F(0x05f79ed9) /* 0.372954225 */, 18 }, + /* 5530 */ { MAD_F(0x05f7fd29) /* 0.373044167 */, 18 }, + /* 5531 */ { MAD_F(0x05f85b7a) /* 0.373134114 */, 18 }, + /* 5532 */ { MAD_F(0x05f8b9cc) /* 0.373224066 */, 18 }, + /* 5533 */ { MAD_F(0x05f91820) /* 0.373314024 */, 18 }, + /* 5534 */ { MAD_F(0x05f97675) /* 0.373403987 */, 18 }, + /* 5535 */ { MAD_F(0x05f9d4cc) /* 0.373493956 */, 18 }, + + /* 5536 */ { MAD_F(0x05fa3324) /* 0.373583930 */, 18 }, + /* 5537 */ { MAD_F(0x05fa917e) /* 0.373673910 */, 18 }, + /* 5538 */ { MAD_F(0x05faefd9) /* 0.373763895 */, 18 }, + /* 5539 */ { MAD_F(0x05fb4e36) /* 0.373853885 */, 18 }, + /* 5540 */ { MAD_F(0x05fbac94) /* 0.373943881 */, 18 }, + /* 5541 */ { MAD_F(0x05fc0af3) /* 0.374033882 */, 18 }, + /* 5542 */ { MAD_F(0x05fc6954) /* 0.374123889 */, 18 }, + /* 5543 */ { MAD_F(0x05fcc7b7) /* 0.374213901 */, 18 }, + /* 5544 */ { MAD_F(0x05fd261b) /* 0.374303918 */, 18 }, + /* 5545 */ { MAD_F(0x05fd8480) /* 0.374393941 */, 18 }, + /* 5546 */ { MAD_F(0x05fde2e7) /* 0.374483970 */, 18 }, + /* 5547 */ { MAD_F(0x05fe414f) /* 0.374574003 */, 18 }, + /* 5548 */ { MAD_F(0x05fe9fb9) /* 0.374664042 */, 18 }, + /* 5549 */ { MAD_F(0x05fefe24) /* 0.374754087 */, 18 }, + /* 5550 */ { MAD_F(0x05ff5c91) /* 0.374844137 */, 18 }, + /* 5551 */ { MAD_F(0x05ffbaff) /* 0.374934192 */, 18 }, + + /* 5552 */ { MAD_F(0x0600196e) /* 0.375024253 */, 18 }, + /* 5553 */ { MAD_F(0x060077df) /* 0.375114319 */, 18 }, + /* 5554 */ { MAD_F(0x0600d651) /* 0.375204391 */, 18 }, + /* 5555 */ { MAD_F(0x060134c5) /* 0.375294468 */, 18 }, + /* 5556 */ { MAD_F(0x0601933b) /* 0.375384550 */, 18 }, + /* 5557 */ { MAD_F(0x0601f1b1) /* 0.375474638 */, 18 }, + /* 5558 */ { MAD_F(0x0602502a) /* 0.375564731 */, 18 }, + /* 5559 */ { MAD_F(0x0602aea3) /* 0.375654830 */, 18 }, + /* 5560 */ { MAD_F(0x06030d1e) /* 0.375744934 */, 18 }, + /* 5561 */ { MAD_F(0x06036b9b) /* 0.375835043 */, 18 }, + /* 5562 */ { MAD_F(0x0603ca19) /* 0.375925158 */, 18 }, + /* 5563 */ { MAD_F(0x06042898) /* 0.376015278 */, 18 }, + /* 5564 */ { MAD_F(0x06048719) /* 0.376105404 */, 18 }, + /* 5565 */ { MAD_F(0x0604e59c) /* 0.376195535 */, 18 }, + /* 5566 */ { MAD_F(0x0605441f) /* 0.376285671 */, 18 }, + /* 5567 */ { MAD_F(0x0605a2a5) /* 0.376375813 */, 18 }, + + /* 5568 */ { MAD_F(0x0606012b) /* 0.376465960 */, 18 }, + /* 5569 */ { MAD_F(0x06065fb4) /* 0.376556113 */, 18 }, + /* 5570 */ { MAD_F(0x0606be3d) /* 0.376646271 */, 18 }, + /* 5571 */ { MAD_F(0x06071cc8) /* 0.376736434 */, 18 }, + /* 5572 */ { MAD_F(0x06077b55) /* 0.376826603 */, 18 }, + /* 5573 */ { MAD_F(0x0607d9e3) /* 0.376916777 */, 18 }, + /* 5574 */ { MAD_F(0x06083872) /* 0.377006957 */, 18 }, + /* 5575 */ { MAD_F(0x06089703) /* 0.377097141 */, 18 }, + /* 5576 */ { MAD_F(0x0608f595) /* 0.377187332 */, 18 }, + /* 5577 */ { MAD_F(0x06095429) /* 0.377277528 */, 18 }, + /* 5578 */ { MAD_F(0x0609b2be) /* 0.377367729 */, 18 }, + /* 5579 */ { MAD_F(0x060a1155) /* 0.377457935 */, 18 }, + /* 5580 */ { MAD_F(0x060a6fed) /* 0.377548147 */, 18 }, + /* 5581 */ { MAD_F(0x060ace86) /* 0.377638364 */, 18 }, + /* 5582 */ { MAD_F(0x060b2d21) /* 0.377728587 */, 18 }, + /* 5583 */ { MAD_F(0x060b8bbe) /* 0.377818815 */, 18 }, + + /* 5584 */ { MAD_F(0x060bea5c) /* 0.377909049 */, 18 }, + /* 5585 */ { MAD_F(0x060c48fb) /* 0.377999288 */, 18 }, + /* 5586 */ { MAD_F(0x060ca79c) /* 0.378089532 */, 18 }, + /* 5587 */ { MAD_F(0x060d063e) /* 0.378179781 */, 18 }, + /* 5588 */ { MAD_F(0x060d64e1) /* 0.378270036 */, 18 }, + /* 5589 */ { MAD_F(0x060dc387) /* 0.378360297 */, 18 }, + /* 5590 */ { MAD_F(0x060e222d) /* 0.378450563 */, 18 }, + /* 5591 */ { MAD_F(0x060e80d5) /* 0.378540834 */, 18 }, + /* 5592 */ { MAD_F(0x060edf7f) /* 0.378631110 */, 18 }, + /* 5593 */ { MAD_F(0x060f3e29) /* 0.378721392 */, 18 }, + /* 5594 */ { MAD_F(0x060f9cd6) /* 0.378811680 */, 18 }, + /* 5595 */ { MAD_F(0x060ffb83) /* 0.378901972 */, 18 }, + /* 5596 */ { MAD_F(0x06105a33) /* 0.378992270 */, 18 }, + /* 5597 */ { MAD_F(0x0610b8e3) /* 0.379082574 */, 18 }, + /* 5598 */ { MAD_F(0x06111795) /* 0.379172883 */, 18 }, + /* 5599 */ { MAD_F(0x06117649) /* 0.379263197 */, 18 }, + + /* 5600 */ { MAD_F(0x0611d4fe) /* 0.379353516 */, 18 }, + /* 5601 */ { MAD_F(0x061233b4) /* 0.379443841 */, 18 }, + /* 5602 */ { MAD_F(0x0612926c) /* 0.379534172 */, 18 }, + /* 5603 */ { MAD_F(0x0612f125) /* 0.379624507 */, 18 }, + /* 5604 */ { MAD_F(0x06134fe0) /* 0.379714848 */, 18 }, + /* 5605 */ { MAD_F(0x0613ae9c) /* 0.379805195 */, 18 }, + /* 5606 */ { MAD_F(0x06140d5a) /* 0.379895547 */, 18 }, + /* 5607 */ { MAD_F(0x06146c19) /* 0.379985904 */, 18 }, + /* 5608 */ { MAD_F(0x0614cada) /* 0.380076266 */, 18 }, + /* 5609 */ { MAD_F(0x0615299c) /* 0.380166634 */, 18 }, + /* 5610 */ { MAD_F(0x0615885f) /* 0.380257008 */, 18 }, + /* 5611 */ { MAD_F(0x0615e724) /* 0.380347386 */, 18 }, + /* 5612 */ { MAD_F(0x061645ea) /* 0.380437770 */, 18 }, + /* 5613 */ { MAD_F(0x0616a4b2) /* 0.380528160 */, 18 }, + /* 5614 */ { MAD_F(0x0617037b) /* 0.380618555 */, 18 }, + /* 5615 */ { MAD_F(0x06176246) /* 0.380708955 */, 18 }, + + /* 5616 */ { MAD_F(0x0617c112) /* 0.380799360 */, 18 }, + /* 5617 */ { MAD_F(0x06181fdf) /* 0.380889771 */, 18 }, + /* 5618 */ { MAD_F(0x06187eae) /* 0.380980187 */, 18 }, + /* 5619 */ { MAD_F(0x0618dd7e) /* 0.381070609 */, 18 }, + /* 5620 */ { MAD_F(0x06193c50) /* 0.381161036 */, 18 }, + /* 5621 */ { MAD_F(0x06199b24) /* 0.381251468 */, 18 }, + /* 5622 */ { MAD_F(0x0619f9f8) /* 0.381341906 */, 18 }, + /* 5623 */ { MAD_F(0x061a58ce) /* 0.381432349 */, 18 }, + /* 5624 */ { MAD_F(0x061ab7a6) /* 0.381522798 */, 18 }, + /* 5625 */ { MAD_F(0x061b167f) /* 0.381613251 */, 18 }, + /* 5626 */ { MAD_F(0x061b7559) /* 0.381703711 */, 18 }, + /* 5627 */ { MAD_F(0x061bd435) /* 0.381794175 */, 18 }, + /* 5628 */ { MAD_F(0x061c3313) /* 0.381884645 */, 18 }, + /* 5629 */ { MAD_F(0x061c91f1) /* 0.381975120 */, 18 }, + /* 5630 */ { MAD_F(0x061cf0d2) /* 0.382065601 */, 18 }, + /* 5631 */ { MAD_F(0x061d4fb3) /* 0.382156087 */, 18 }, + + /* 5632 */ { MAD_F(0x061dae96) /* 0.382246578 */, 18 }, + /* 5633 */ { MAD_F(0x061e0d7b) /* 0.382337075 */, 18 }, + /* 5634 */ { MAD_F(0x061e6c61) /* 0.382427577 */, 18 }, + /* 5635 */ { MAD_F(0x061ecb48) /* 0.382518084 */, 18 }, + /* 5636 */ { MAD_F(0x061f2a31) /* 0.382608597 */, 18 }, + /* 5637 */ { MAD_F(0x061f891b) /* 0.382699115 */, 18 }, + /* 5638 */ { MAD_F(0x061fe807) /* 0.382789638 */, 18 }, + /* 5639 */ { MAD_F(0x062046f4) /* 0.382880167 */, 18 }, + /* 5640 */ { MAD_F(0x0620a5e3) /* 0.382970701 */, 18 }, + /* 5641 */ { MAD_F(0x062104d3) /* 0.383061241 */, 18 }, + /* 5642 */ { MAD_F(0x062163c4) /* 0.383151786 */, 18 }, + /* 5643 */ { MAD_F(0x0621c2b7) /* 0.383242336 */, 18 }, + /* 5644 */ { MAD_F(0x062221ab) /* 0.383332891 */, 18 }, + /* 5645 */ { MAD_F(0x062280a1) /* 0.383423452 */, 18 }, + /* 5646 */ { MAD_F(0x0622df98) /* 0.383514018 */, 18 }, + /* 5647 */ { MAD_F(0x06233e91) /* 0.383604590 */, 18 }, + + /* 5648 */ { MAD_F(0x06239d8b) /* 0.383695167 */, 18 }, + /* 5649 */ { MAD_F(0x0623fc86) /* 0.383785749 */, 18 }, + /* 5650 */ { MAD_F(0x06245b83) /* 0.383876337 */, 18 }, + /* 5651 */ { MAD_F(0x0624ba82) /* 0.383966930 */, 18 }, + /* 5652 */ { MAD_F(0x06251981) /* 0.384057528 */, 18 }, + /* 5653 */ { MAD_F(0x06257883) /* 0.384148132 */, 18 }, + /* 5654 */ { MAD_F(0x0625d785) /* 0.384238741 */, 18 }, + /* 5655 */ { MAD_F(0x06263689) /* 0.384329355 */, 18 }, + /* 5656 */ { MAD_F(0x0626958f) /* 0.384419975 */, 18 }, + /* 5657 */ { MAD_F(0x0626f496) /* 0.384510600 */, 18 }, + /* 5658 */ { MAD_F(0x0627539e) /* 0.384601230 */, 18 }, + /* 5659 */ { MAD_F(0x0627b2a8) /* 0.384691866 */, 18 }, + /* 5660 */ { MAD_F(0x062811b3) /* 0.384782507 */, 18 }, + /* 5661 */ { MAD_F(0x062870c0) /* 0.384873153 */, 18 }, + /* 5662 */ { MAD_F(0x0628cfce) /* 0.384963805 */, 18 }, + /* 5663 */ { MAD_F(0x06292ede) /* 0.385054462 */, 18 }, + + /* 5664 */ { MAD_F(0x06298def) /* 0.385145124 */, 18 }, + /* 5665 */ { MAD_F(0x0629ed01) /* 0.385235792 */, 18 }, + /* 5666 */ { MAD_F(0x062a4c15) /* 0.385326465 */, 18 }, + /* 5667 */ { MAD_F(0x062aab2a) /* 0.385417143 */, 18 }, + /* 5668 */ { MAD_F(0x062b0a41) /* 0.385507827 */, 18 }, + /* 5669 */ { MAD_F(0x062b6959) /* 0.385598516 */, 18 }, + /* 5670 */ { MAD_F(0x062bc873) /* 0.385689211 */, 18 }, + /* 5671 */ { MAD_F(0x062c278e) /* 0.385779910 */, 18 }, + /* 5672 */ { MAD_F(0x062c86aa) /* 0.385870615 */, 18 }, + /* 5673 */ { MAD_F(0x062ce5c8) /* 0.385961326 */, 18 }, + /* 5674 */ { MAD_F(0x062d44e8) /* 0.386052041 */, 18 }, + /* 5675 */ { MAD_F(0x062da408) /* 0.386142762 */, 18 }, + /* 5676 */ { MAD_F(0x062e032a) /* 0.386233489 */, 18 }, + /* 5677 */ { MAD_F(0x062e624e) /* 0.386324221 */, 18 }, + /* 5678 */ { MAD_F(0x062ec173) /* 0.386414958 */, 18 }, + /* 5679 */ { MAD_F(0x062f209a) /* 0.386505700 */, 18 }, + + /* 5680 */ { MAD_F(0x062f7fc1) /* 0.386596448 */, 18 }, + /* 5681 */ { MAD_F(0x062fdeeb) /* 0.386687201 */, 18 }, + /* 5682 */ { MAD_F(0x06303e16) /* 0.386777959 */, 18 }, + /* 5683 */ { MAD_F(0x06309d42) /* 0.386868723 */, 18 }, + /* 5684 */ { MAD_F(0x0630fc6f) /* 0.386959492 */, 18 }, + /* 5685 */ { MAD_F(0x06315b9e) /* 0.387050266 */, 18 }, + /* 5686 */ { MAD_F(0x0631bacf) /* 0.387141045 */, 18 }, + /* 5687 */ { MAD_F(0x06321a01) /* 0.387231830 */, 18 }, + /* 5688 */ { MAD_F(0x06327934) /* 0.387322621 */, 18 }, + /* 5689 */ { MAD_F(0x0632d869) /* 0.387413416 */, 18 }, + /* 5690 */ { MAD_F(0x0633379f) /* 0.387504217 */, 18 }, + /* 5691 */ { MAD_F(0x063396d7) /* 0.387595023 */, 18 }, + /* 5692 */ { MAD_F(0x0633f610) /* 0.387685835 */, 18 }, + /* 5693 */ { MAD_F(0x0634554a) /* 0.387776652 */, 18 }, + /* 5694 */ { MAD_F(0x0634b486) /* 0.387867474 */, 18 }, + /* 5695 */ { MAD_F(0x063513c3) /* 0.387958301 */, 18 }, + + /* 5696 */ { MAD_F(0x06357302) /* 0.388049134 */, 18 }, + /* 5697 */ { MAD_F(0x0635d242) /* 0.388139972 */, 18 }, + /* 5698 */ { MAD_F(0x06363184) /* 0.388230816 */, 18 }, + /* 5699 */ { MAD_F(0x063690c7) /* 0.388321665 */, 18 }, + /* 5700 */ { MAD_F(0x0636f00b) /* 0.388412519 */, 18 }, + /* 5701 */ { MAD_F(0x06374f51) /* 0.388503378 */, 18 }, + /* 5702 */ { MAD_F(0x0637ae99) /* 0.388594243 */, 18 }, + /* 5703 */ { MAD_F(0x06380de1) /* 0.388685113 */, 18 }, + /* 5704 */ { MAD_F(0x06386d2b) /* 0.388775988 */, 18 }, + /* 5705 */ { MAD_F(0x0638cc77) /* 0.388866869 */, 18 }, + /* 5706 */ { MAD_F(0x06392bc4) /* 0.388957755 */, 18 }, + /* 5707 */ { MAD_F(0x06398b12) /* 0.389048646 */, 18 }, + /* 5708 */ { MAD_F(0x0639ea62) /* 0.389139542 */, 18 }, + /* 5709 */ { MAD_F(0x063a49b4) /* 0.389230444 */, 18 }, + /* 5710 */ { MAD_F(0x063aa906) /* 0.389321352 */, 18 }, + /* 5711 */ { MAD_F(0x063b085a) /* 0.389412264 */, 18 }, + + /* 5712 */ { MAD_F(0x063b67b0) /* 0.389503182 */, 18 }, + /* 5713 */ { MAD_F(0x063bc707) /* 0.389594105 */, 18 }, + /* 5714 */ { MAD_F(0x063c265f) /* 0.389685033 */, 18 }, + /* 5715 */ { MAD_F(0x063c85b9) /* 0.389775967 */, 18 }, + /* 5716 */ { MAD_F(0x063ce514) /* 0.389866906 */, 18 }, + /* 5717 */ { MAD_F(0x063d4471) /* 0.389957850 */, 18 }, + /* 5718 */ { MAD_F(0x063da3cf) /* 0.390048800 */, 18 }, + /* 5719 */ { MAD_F(0x063e032f) /* 0.390139755 */, 18 }, + /* 5720 */ { MAD_F(0x063e6290) /* 0.390230715 */, 18 }, + /* 5721 */ { MAD_F(0x063ec1f2) /* 0.390321681 */, 18 }, + /* 5722 */ { MAD_F(0x063f2156) /* 0.390412651 */, 18 }, + /* 5723 */ { MAD_F(0x063f80bb) /* 0.390503628 */, 18 }, + /* 5724 */ { MAD_F(0x063fe022) /* 0.390594609 */, 18 }, + /* 5725 */ { MAD_F(0x06403f8a) /* 0.390685596 */, 18 }, + /* 5726 */ { MAD_F(0x06409ef3) /* 0.390776588 */, 18 }, + /* 5727 */ { MAD_F(0x0640fe5e) /* 0.390867585 */, 18 }, + + /* 5728 */ { MAD_F(0x06415dcb) /* 0.390958588 */, 18 }, + /* 5729 */ { MAD_F(0x0641bd38) /* 0.391049596 */, 18 }, + /* 5730 */ { MAD_F(0x06421ca7) /* 0.391140609 */, 18 }, + /* 5731 */ { MAD_F(0x06427c18) /* 0.391231627 */, 18 }, + /* 5732 */ { MAD_F(0x0642db8a) /* 0.391322651 */, 18 }, + /* 5733 */ { MAD_F(0x06433afd) /* 0.391413680 */, 18 }, + /* 5734 */ { MAD_F(0x06439a72) /* 0.391504714 */, 18 }, + /* 5735 */ { MAD_F(0x0643f9e9) /* 0.391595754 */, 18 }, + /* 5736 */ { MAD_F(0x06445960) /* 0.391686799 */, 18 }, + /* 5737 */ { MAD_F(0x0644b8d9) /* 0.391777849 */, 18 }, + /* 5738 */ { MAD_F(0x06451854) /* 0.391868905 */, 18 }, + /* 5739 */ { MAD_F(0x064577d0) /* 0.391959966 */, 18 }, + /* 5740 */ { MAD_F(0x0645d74d) /* 0.392051032 */, 18 }, + /* 5741 */ { MAD_F(0x064636cc) /* 0.392142103 */, 18 }, + /* 5742 */ { MAD_F(0x0646964c) /* 0.392233180 */, 18 }, + /* 5743 */ { MAD_F(0x0646f5ce) /* 0.392324262 */, 18 }, + + /* 5744 */ { MAD_F(0x06475551) /* 0.392415349 */, 18 }, + /* 5745 */ { MAD_F(0x0647b4d5) /* 0.392506442 */, 18 }, + /* 5746 */ { MAD_F(0x0648145b) /* 0.392597540 */, 18 }, + /* 5747 */ { MAD_F(0x064873e3) /* 0.392688643 */, 18 }, + /* 5748 */ { MAD_F(0x0648d36b) /* 0.392779751 */, 18 }, + /* 5749 */ { MAD_F(0x064932f6) /* 0.392870865 */, 18 }, + /* 5750 */ { MAD_F(0x06499281) /* 0.392961984 */, 18 }, + /* 5751 */ { MAD_F(0x0649f20e) /* 0.393053108 */, 18 }, + /* 5752 */ { MAD_F(0x064a519c) /* 0.393144238 */, 18 }, + /* 5753 */ { MAD_F(0x064ab12c) /* 0.393235372 */, 18 }, + /* 5754 */ { MAD_F(0x064b10be) /* 0.393326513 */, 18 }, + /* 5755 */ { MAD_F(0x064b7050) /* 0.393417658 */, 18 }, + /* 5756 */ { MAD_F(0x064bcfe4) /* 0.393508809 */, 18 }, + /* 5757 */ { MAD_F(0x064c2f7a) /* 0.393599965 */, 18 }, + /* 5758 */ { MAD_F(0x064c8f11) /* 0.393691126 */, 18 }, + /* 5759 */ { MAD_F(0x064ceea9) /* 0.393782292 */, 18 }, + + /* 5760 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 18 }, + /* 5761 */ { MAD_F(0x064dadde) /* 0.393964641 */, 18 }, + /* 5762 */ { MAD_F(0x064e0d7a) /* 0.394055823 */, 18 }, + /* 5763 */ { MAD_F(0x064e6d18) /* 0.394147011 */, 18 }, + /* 5764 */ { MAD_F(0x064eccb8) /* 0.394238204 */, 18 }, + /* 5765 */ { MAD_F(0x064f2c59) /* 0.394329402 */, 18 }, + /* 5766 */ { MAD_F(0x064f8bfb) /* 0.394420605 */, 18 }, + /* 5767 */ { MAD_F(0x064feb9e) /* 0.394511814 */, 18 }, + /* 5768 */ { MAD_F(0x06504b44) /* 0.394603028 */, 18 }, + /* 5769 */ { MAD_F(0x0650aaea) /* 0.394694247 */, 18 }, + /* 5770 */ { MAD_F(0x06510a92) /* 0.394785472 */, 18 }, + /* 5771 */ { MAD_F(0x06516a3b) /* 0.394876702 */, 18 }, + /* 5772 */ { MAD_F(0x0651c9e6) /* 0.394967937 */, 18 }, + /* 5773 */ { MAD_F(0x06522992) /* 0.395059177 */, 18 }, + /* 5774 */ { MAD_F(0x06528940) /* 0.395150423 */, 18 }, + /* 5775 */ { MAD_F(0x0652e8ef) /* 0.395241673 */, 18 }, + + /* 5776 */ { MAD_F(0x0653489f) /* 0.395332930 */, 18 }, + /* 5777 */ { MAD_F(0x0653a851) /* 0.395424191 */, 18 }, + /* 5778 */ { MAD_F(0x06540804) /* 0.395515458 */, 18 }, + /* 5779 */ { MAD_F(0x065467b9) /* 0.395606730 */, 18 }, + /* 5780 */ { MAD_F(0x0654c76f) /* 0.395698007 */, 18 }, + /* 5781 */ { MAD_F(0x06552726) /* 0.395789289 */, 18 }, + /* 5782 */ { MAD_F(0x065586df) /* 0.395880577 */, 18 }, + /* 5783 */ { MAD_F(0x0655e699) /* 0.395971870 */, 18 }, + /* 5784 */ { MAD_F(0x06564655) /* 0.396063168 */, 18 }, + /* 5785 */ { MAD_F(0x0656a612) /* 0.396154472 */, 18 }, + /* 5786 */ { MAD_F(0x065705d0) /* 0.396245780 */, 18 }, + /* 5787 */ { MAD_F(0x06576590) /* 0.396337094 */, 18 }, + /* 5788 */ { MAD_F(0x0657c552) /* 0.396428414 */, 18 }, + /* 5789 */ { MAD_F(0x06582514) /* 0.396519738 */, 18 }, + /* 5790 */ { MAD_F(0x065884d9) /* 0.396611068 */, 18 }, + /* 5791 */ { MAD_F(0x0658e49e) /* 0.396702403 */, 18 }, + + /* 5792 */ { MAD_F(0x06594465) /* 0.396793743 */, 18 }, + /* 5793 */ { MAD_F(0x0659a42e) /* 0.396885089 */, 18 }, + /* 5794 */ { MAD_F(0x065a03f7) /* 0.396976440 */, 18 }, + /* 5795 */ { MAD_F(0x065a63c3) /* 0.397067796 */, 18 }, + /* 5796 */ { MAD_F(0x065ac38f) /* 0.397159157 */, 18 }, + /* 5797 */ { MAD_F(0x065b235d) /* 0.397250524 */, 18 }, + /* 5798 */ { MAD_F(0x065b832d) /* 0.397341896 */, 18 }, + /* 5799 */ { MAD_F(0x065be2fe) /* 0.397433273 */, 18 }, + /* 5800 */ { MAD_F(0x065c42d0) /* 0.397524655 */, 18 }, + /* 5801 */ { MAD_F(0x065ca2a3) /* 0.397616043 */, 18 }, + /* 5802 */ { MAD_F(0x065d0279) /* 0.397707436 */, 18 }, + /* 5803 */ { MAD_F(0x065d624f) /* 0.397798834 */, 18 }, + /* 5804 */ { MAD_F(0x065dc227) /* 0.397890237 */, 18 }, + /* 5805 */ { MAD_F(0x065e2200) /* 0.397981646 */, 18 }, + /* 5806 */ { MAD_F(0x065e81db) /* 0.398073059 */, 18 }, + /* 5807 */ { MAD_F(0x065ee1b7) /* 0.398164479 */, 18 }, + + /* 5808 */ { MAD_F(0x065f4195) /* 0.398255903 */, 18 }, + /* 5809 */ { MAD_F(0x065fa174) /* 0.398347333 */, 18 }, + /* 5810 */ { MAD_F(0x06600154) /* 0.398438767 */, 18 }, + /* 5811 */ { MAD_F(0x06606136) /* 0.398530207 */, 18 }, + /* 5812 */ { MAD_F(0x0660c119) /* 0.398621653 */, 18 }, + /* 5813 */ { MAD_F(0x066120fd) /* 0.398713103 */, 18 }, + /* 5814 */ { MAD_F(0x066180e3) /* 0.398804559 */, 18 }, + /* 5815 */ { MAD_F(0x0661e0cb) /* 0.398896020 */, 18 }, + /* 5816 */ { MAD_F(0x066240b4) /* 0.398987487 */, 18 }, + /* 5817 */ { MAD_F(0x0662a09e) /* 0.399078958 */, 18 }, + /* 5818 */ { MAD_F(0x06630089) /* 0.399170435 */, 18 }, + /* 5819 */ { MAD_F(0x06636077) /* 0.399261917 */, 18 }, + /* 5820 */ { MAD_F(0x0663c065) /* 0.399353404 */, 18 }, + /* 5821 */ { MAD_F(0x06642055) /* 0.399444897 */, 18 }, + /* 5822 */ { MAD_F(0x06648046) /* 0.399536395 */, 18 }, + /* 5823 */ { MAD_F(0x0664e039) /* 0.399627898 */, 18 }, + + /* 5824 */ { MAD_F(0x0665402d) /* 0.399719406 */, 18 }, + /* 5825 */ { MAD_F(0x0665a022) /* 0.399810919 */, 18 }, + /* 5826 */ { MAD_F(0x06660019) /* 0.399902438 */, 18 }, + /* 5827 */ { MAD_F(0x06666011) /* 0.399993962 */, 18 }, + /* 5828 */ { MAD_F(0x0666c00b) /* 0.400085491 */, 18 }, + /* 5829 */ { MAD_F(0x06672006) /* 0.400177026 */, 18 }, + /* 5830 */ { MAD_F(0x06678003) /* 0.400268565 */, 18 }, + /* 5831 */ { MAD_F(0x0667e000) /* 0.400360110 */, 18 }, + /* 5832 */ { MAD_F(0x06684000) /* 0.400451660 */, 18 }, + /* 5833 */ { MAD_F(0x0668a000) /* 0.400543216 */, 18 }, + /* 5834 */ { MAD_F(0x06690003) /* 0.400634776 */, 18 }, + /* 5835 */ { MAD_F(0x06696006) /* 0.400726342 */, 18 }, + /* 5836 */ { MAD_F(0x0669c00b) /* 0.400817913 */, 18 }, + /* 5837 */ { MAD_F(0x066a2011) /* 0.400909489 */, 18 }, + /* 5838 */ { MAD_F(0x066a8019) /* 0.401001071 */, 18 }, + /* 5839 */ { MAD_F(0x066ae022) /* 0.401092657 */, 18 }, + + /* 5840 */ { MAD_F(0x066b402d) /* 0.401184249 */, 18 }, + /* 5841 */ { MAD_F(0x066ba039) /* 0.401275847 */, 18 }, + /* 5842 */ { MAD_F(0x066c0046) /* 0.401367449 */, 18 }, + /* 5843 */ { MAD_F(0x066c6055) /* 0.401459057 */, 18 }, + /* 5844 */ { MAD_F(0x066cc065) /* 0.401550670 */, 18 }, + /* 5845 */ { MAD_F(0x066d2076) /* 0.401642288 */, 18 }, + /* 5846 */ { MAD_F(0x066d8089) /* 0.401733911 */, 18 }, + /* 5847 */ { MAD_F(0x066de09e) /* 0.401825540 */, 18 }, + /* 5848 */ { MAD_F(0x066e40b3) /* 0.401917173 */, 18 }, + /* 5849 */ { MAD_F(0x066ea0cb) /* 0.402008812 */, 18 }, + /* 5850 */ { MAD_F(0x066f00e3) /* 0.402100457 */, 18 }, + /* 5851 */ { MAD_F(0x066f60fd) /* 0.402192106 */, 18 }, + /* 5852 */ { MAD_F(0x066fc118) /* 0.402283761 */, 18 }, + /* 5853 */ { MAD_F(0x06702135) /* 0.402375420 */, 18 }, + /* 5854 */ { MAD_F(0x06708153) /* 0.402467086 */, 18 }, + /* 5855 */ { MAD_F(0x0670e173) /* 0.402558756 */, 18 }, + + /* 5856 */ { MAD_F(0x06714194) /* 0.402650431 */, 18 }, + /* 5857 */ { MAD_F(0x0671a1b6) /* 0.402742112 */, 18 }, + /* 5858 */ { MAD_F(0x067201da) /* 0.402833798 */, 18 }, + /* 5859 */ { MAD_F(0x067261ff) /* 0.402925489 */, 18 }, + /* 5860 */ { MAD_F(0x0672c226) /* 0.403017186 */, 18 }, + /* 5861 */ { MAD_F(0x0673224e) /* 0.403108887 */, 18 }, + /* 5862 */ { MAD_F(0x06738277) /* 0.403200594 */, 18 }, + /* 5863 */ { MAD_F(0x0673e2a2) /* 0.403292306 */, 18 }, + /* 5864 */ { MAD_F(0x067442ce) /* 0.403384024 */, 18 }, + /* 5865 */ { MAD_F(0x0674a2fc) /* 0.403475746 */, 18 }, + /* 5866 */ { MAD_F(0x0675032b) /* 0.403567474 */, 18 }, + /* 5867 */ { MAD_F(0x0675635b) /* 0.403659207 */, 18 }, + /* 5868 */ { MAD_F(0x0675c38d) /* 0.403750945 */, 18 }, + /* 5869 */ { MAD_F(0x067623c0) /* 0.403842688 */, 18 }, + /* 5870 */ { MAD_F(0x067683f4) /* 0.403934437 */, 18 }, + /* 5871 */ { MAD_F(0x0676e42a) /* 0.404026190 */, 18 }, + + /* 5872 */ { MAD_F(0x06774462) /* 0.404117949 */, 18 }, + /* 5873 */ { MAD_F(0x0677a49b) /* 0.404209714 */, 18 }, + /* 5874 */ { MAD_F(0x067804d5) /* 0.404301483 */, 18 }, + /* 5875 */ { MAD_F(0x06786510) /* 0.404393258 */, 18 }, + /* 5876 */ { MAD_F(0x0678c54d) /* 0.404485037 */, 18 }, + /* 5877 */ { MAD_F(0x0679258c) /* 0.404576822 */, 18 }, + /* 5878 */ { MAD_F(0x067985cb) /* 0.404668613 */, 18 }, + /* 5879 */ { MAD_F(0x0679e60c) /* 0.404760408 */, 18 }, + /* 5880 */ { MAD_F(0x067a464f) /* 0.404852209 */, 18 }, + /* 5881 */ { MAD_F(0x067aa693) /* 0.404944014 */, 18 }, + /* 5882 */ { MAD_F(0x067b06d8) /* 0.405035825 */, 18 }, + /* 5883 */ { MAD_F(0x067b671f) /* 0.405127642 */, 18 }, + /* 5884 */ { MAD_F(0x067bc767) /* 0.405219463 */, 18 }, + /* 5885 */ { MAD_F(0x067c27b1) /* 0.405311290 */, 18 }, + /* 5886 */ { MAD_F(0x067c87fc) /* 0.405403122 */, 18 }, + /* 5887 */ { MAD_F(0x067ce848) /* 0.405494959 */, 18 }, + + /* 5888 */ { MAD_F(0x067d4896) /* 0.405586801 */, 18 }, + /* 5889 */ { MAD_F(0x067da8e5) /* 0.405678648 */, 18 }, + /* 5890 */ { MAD_F(0x067e0935) /* 0.405770501 */, 18 }, + /* 5891 */ { MAD_F(0x067e6987) /* 0.405862359 */, 18 }, + /* 5892 */ { MAD_F(0x067ec9da) /* 0.405954222 */, 18 }, + /* 5893 */ { MAD_F(0x067f2a2f) /* 0.406046090 */, 18 }, + /* 5894 */ { MAD_F(0x067f8a85) /* 0.406137963 */, 18 }, + /* 5895 */ { MAD_F(0x067feadd) /* 0.406229842 */, 18 }, + /* 5896 */ { MAD_F(0x06804b36) /* 0.406321726 */, 18 }, + /* 5897 */ { MAD_F(0x0680ab90) /* 0.406413615 */, 18 }, + /* 5898 */ { MAD_F(0x06810beb) /* 0.406505509 */, 18 }, + /* 5899 */ { MAD_F(0x06816c49) /* 0.406597408 */, 18 }, + /* 5900 */ { MAD_F(0x0681cca7) /* 0.406689313 */, 18 }, + /* 5901 */ { MAD_F(0x06822d07) /* 0.406781223 */, 18 }, + /* 5902 */ { MAD_F(0x06828d68) /* 0.406873138 */, 18 }, + /* 5903 */ { MAD_F(0x0682edcb) /* 0.406965058 */, 18 }, + + /* 5904 */ { MAD_F(0x06834e2f) /* 0.407056983 */, 18 }, + /* 5905 */ { MAD_F(0x0683ae94) /* 0.407148914 */, 18 }, + /* 5906 */ { MAD_F(0x06840efb) /* 0.407240850 */, 18 }, + /* 5907 */ { MAD_F(0x06846f63) /* 0.407332791 */, 18 }, + /* 5908 */ { MAD_F(0x0684cfcd) /* 0.407424737 */, 18 }, + /* 5909 */ { MAD_F(0x06853038) /* 0.407516688 */, 18 }, + /* 5910 */ { MAD_F(0x068590a4) /* 0.407608645 */, 18 }, + /* 5911 */ { MAD_F(0x0685f112) /* 0.407700606 */, 18 }, + /* 5912 */ { MAD_F(0x06865181) /* 0.407792573 */, 18 }, + /* 5913 */ { MAD_F(0x0686b1f2) /* 0.407884545 */, 18 }, + /* 5914 */ { MAD_F(0x06871264) /* 0.407976522 */, 18 }, + /* 5915 */ { MAD_F(0x068772d7) /* 0.408068505 */, 18 }, + /* 5916 */ { MAD_F(0x0687d34c) /* 0.408160492 */, 18 }, + /* 5917 */ { MAD_F(0x068833c2) /* 0.408252485 */, 18 }, + /* 5918 */ { MAD_F(0x06889439) /* 0.408344483 */, 18 }, + /* 5919 */ { MAD_F(0x0688f4b2) /* 0.408436486 */, 18 }, + + /* 5920 */ { MAD_F(0x0689552c) /* 0.408528495 */, 18 }, + /* 5921 */ { MAD_F(0x0689b5a8) /* 0.408620508 */, 18 }, + /* 5922 */ { MAD_F(0x068a1625) /* 0.408712527 */, 18 }, + /* 5923 */ { MAD_F(0x068a76a4) /* 0.408804551 */, 18 }, + /* 5924 */ { MAD_F(0x068ad724) /* 0.408896580 */, 18 }, + /* 5925 */ { MAD_F(0x068b37a5) /* 0.408988614 */, 18 }, + /* 5926 */ { MAD_F(0x068b9827) /* 0.409080653 */, 18 }, + /* 5927 */ { MAD_F(0x068bf8ac) /* 0.409172698 */, 18 }, + /* 5928 */ { MAD_F(0x068c5931) /* 0.409264748 */, 18 }, + /* 5929 */ { MAD_F(0x068cb9b8) /* 0.409356803 */, 18 }, + /* 5930 */ { MAD_F(0x068d1a40) /* 0.409448863 */, 18 }, + /* 5931 */ { MAD_F(0x068d7aca) /* 0.409540928 */, 18 }, + /* 5932 */ { MAD_F(0x068ddb54) /* 0.409632999 */, 18 }, + /* 5933 */ { MAD_F(0x068e3be1) /* 0.409725074 */, 18 }, + /* 5934 */ { MAD_F(0x068e9c6f) /* 0.409817155 */, 18 }, + /* 5935 */ { MAD_F(0x068efcfe) /* 0.409909241 */, 18 }, + + /* 5936 */ { MAD_F(0x068f5d8e) /* 0.410001332 */, 18 }, + /* 5937 */ { MAD_F(0x068fbe20) /* 0.410093428 */, 18 }, + /* 5938 */ { MAD_F(0x06901eb4) /* 0.410185530 */, 18 }, + /* 5939 */ { MAD_F(0x06907f48) /* 0.410277637 */, 18 }, + /* 5940 */ { MAD_F(0x0690dfde) /* 0.410369748 */, 18 }, + /* 5941 */ { MAD_F(0x06914076) /* 0.410461865 */, 18 }, + /* 5942 */ { MAD_F(0x0691a10f) /* 0.410553988 */, 18 }, + /* 5943 */ { MAD_F(0x069201a9) /* 0.410646115 */, 18 }, + /* 5944 */ { MAD_F(0x06926245) /* 0.410738247 */, 18 }, + /* 5945 */ { MAD_F(0x0692c2e2) /* 0.410830385 */, 18 }, + /* 5946 */ { MAD_F(0x06932380) /* 0.410922528 */, 18 }, + /* 5947 */ { MAD_F(0x06938420) /* 0.411014676 */, 18 }, + /* 5948 */ { MAD_F(0x0693e4c1) /* 0.411106829 */, 18 }, + /* 5949 */ { MAD_F(0x06944563) /* 0.411198987 */, 18 }, + /* 5950 */ { MAD_F(0x0694a607) /* 0.411291151 */, 18 }, + /* 5951 */ { MAD_F(0x069506ad) /* 0.411383320 */, 18 }, + + /* 5952 */ { MAD_F(0x06956753) /* 0.411475493 */, 18 }, + /* 5953 */ { MAD_F(0x0695c7fc) /* 0.411567672 */, 18 }, + /* 5954 */ { MAD_F(0x069628a5) /* 0.411659857 */, 18 }, + /* 5955 */ { MAD_F(0x06968950) /* 0.411752046 */, 18 }, + /* 5956 */ { MAD_F(0x0696e9fc) /* 0.411844240 */, 18 }, + /* 5957 */ { MAD_F(0x06974aaa) /* 0.411936440 */, 18 }, + /* 5958 */ { MAD_F(0x0697ab59) /* 0.412028645 */, 18 }, + /* 5959 */ { MAD_F(0x06980c09) /* 0.412120855 */, 18 }, + /* 5960 */ { MAD_F(0x06986cbb) /* 0.412213070 */, 18 }, + /* 5961 */ { MAD_F(0x0698cd6e) /* 0.412305290 */, 18 }, + /* 5962 */ { MAD_F(0x06992e23) /* 0.412397516 */, 18 }, + /* 5963 */ { MAD_F(0x06998ed9) /* 0.412489746 */, 18 }, + /* 5964 */ { MAD_F(0x0699ef90) /* 0.412581982 */, 18 }, + /* 5965 */ { MAD_F(0x069a5049) /* 0.412674223 */, 18 }, + /* 5966 */ { MAD_F(0x069ab103) /* 0.412766469 */, 18 }, + /* 5967 */ { MAD_F(0x069b11bf) /* 0.412858720 */, 18 }, + + /* 5968 */ { MAD_F(0x069b727b) /* 0.412950976 */, 18 }, + /* 5969 */ { MAD_F(0x069bd33a) /* 0.413043238 */, 18 }, + /* 5970 */ { MAD_F(0x069c33f9) /* 0.413135505 */, 18 }, + /* 5971 */ { MAD_F(0x069c94ba) /* 0.413227776 */, 18 }, + /* 5972 */ { MAD_F(0x069cf57d) /* 0.413320053 */, 18 }, + /* 5973 */ { MAD_F(0x069d5641) /* 0.413412335 */, 18 }, + /* 5974 */ { MAD_F(0x069db706) /* 0.413504623 */, 18 }, + /* 5975 */ { MAD_F(0x069e17cc) /* 0.413596915 */, 18 }, + /* 5976 */ { MAD_F(0x069e7894) /* 0.413689213 */, 18 }, + /* 5977 */ { MAD_F(0x069ed95e) /* 0.413781515 */, 18 }, + /* 5978 */ { MAD_F(0x069f3a28) /* 0.413873823 */, 18 }, + /* 5979 */ { MAD_F(0x069f9af4) /* 0.413966136 */, 18 }, + /* 5980 */ { MAD_F(0x069ffbc2) /* 0.414058454 */, 18 }, + /* 5981 */ { MAD_F(0x06a05c91) /* 0.414150778 */, 18 }, + /* 5982 */ { MAD_F(0x06a0bd61) /* 0.414243106 */, 18 }, + /* 5983 */ { MAD_F(0x06a11e32) /* 0.414335440 */, 18 }, + + /* 5984 */ { MAD_F(0x06a17f05) /* 0.414427779 */, 18 }, + /* 5985 */ { MAD_F(0x06a1dfda) /* 0.414520122 */, 18 }, + /* 5986 */ { MAD_F(0x06a240b0) /* 0.414612471 */, 18 }, + /* 5987 */ { MAD_F(0x06a2a187) /* 0.414704826 */, 18 }, + /* 5988 */ { MAD_F(0x06a3025f) /* 0.414797185 */, 18 }, + /* 5989 */ { MAD_F(0x06a36339) /* 0.414889549 */, 18 }, + /* 5990 */ { MAD_F(0x06a3c414) /* 0.414981919 */, 18 }, + /* 5991 */ { MAD_F(0x06a424f1) /* 0.415074294 */, 18 }, + /* 5992 */ { MAD_F(0x06a485cf) /* 0.415166674 */, 18 }, + /* 5993 */ { MAD_F(0x06a4e6ae) /* 0.415259059 */, 18 }, + /* 5994 */ { MAD_F(0x06a5478f) /* 0.415351449 */, 18 }, + /* 5995 */ { MAD_F(0x06a5a871) /* 0.415443844 */, 18 }, + /* 5996 */ { MAD_F(0x06a60955) /* 0.415536244 */, 18 }, + /* 5997 */ { MAD_F(0x06a66a3a) /* 0.415628650 */, 18 }, + /* 5998 */ { MAD_F(0x06a6cb20) /* 0.415721061 */, 18 }, + /* 5999 */ { MAD_F(0x06a72c08) /* 0.415813476 */, 18 }, + + /* 6000 */ { MAD_F(0x06a78cf1) /* 0.415905897 */, 18 }, + /* 6001 */ { MAD_F(0x06a7eddb) /* 0.415998324 */, 18 }, + /* 6002 */ { MAD_F(0x06a84ec7) /* 0.416090755 */, 18 }, + /* 6003 */ { MAD_F(0x06a8afb4) /* 0.416183191 */, 18 }, + /* 6004 */ { MAD_F(0x06a910a3) /* 0.416275633 */, 18 }, + /* 6005 */ { MAD_F(0x06a97193) /* 0.416368079 */, 18 }, + /* 6006 */ { MAD_F(0x06a9d284) /* 0.416460531 */, 18 }, + /* 6007 */ { MAD_F(0x06aa3377) /* 0.416552988 */, 18 }, + /* 6008 */ { MAD_F(0x06aa946b) /* 0.416645450 */, 18 }, + /* 6009 */ { MAD_F(0x06aaf561) /* 0.416737917 */, 18 }, + /* 6010 */ { MAD_F(0x06ab5657) /* 0.416830389 */, 18 }, + /* 6011 */ { MAD_F(0x06abb750) /* 0.416922867 */, 18 }, + /* 6012 */ { MAD_F(0x06ac1849) /* 0.417015349 */, 18 }, + /* 6013 */ { MAD_F(0x06ac7944) /* 0.417107837 */, 18 }, + /* 6014 */ { MAD_F(0x06acda41) /* 0.417200330 */, 18 }, + /* 6015 */ { MAD_F(0x06ad3b3e) /* 0.417292828 */, 18 }, + + /* 6016 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 18 }, + /* 6017 */ { MAD_F(0x06adfd3e) /* 0.417477839 */, 18 }, + /* 6018 */ { MAD_F(0x06ae5e40) /* 0.417570352 */, 18 }, + /* 6019 */ { MAD_F(0x06aebf43) /* 0.417662871 */, 18 }, + /* 6020 */ { MAD_F(0x06af2047) /* 0.417755394 */, 18 }, + /* 6021 */ { MAD_F(0x06af814d) /* 0.417847923 */, 18 }, + /* 6022 */ { MAD_F(0x06afe255) /* 0.417940457 */, 18 }, + /* 6023 */ { MAD_F(0x06b0435e) /* 0.418032996 */, 18 }, + /* 6024 */ { MAD_F(0x06b0a468) /* 0.418125540 */, 18 }, + /* 6025 */ { MAD_F(0x06b10573) /* 0.418218089 */, 18 }, + /* 6026 */ { MAD_F(0x06b16680) /* 0.418310643 */, 18 }, + /* 6027 */ { MAD_F(0x06b1c78e) /* 0.418403203 */, 18 }, + /* 6028 */ { MAD_F(0x06b2289e) /* 0.418495767 */, 18 }, + /* 6029 */ { MAD_F(0x06b289af) /* 0.418588337 */, 18 }, + /* 6030 */ { MAD_F(0x06b2eac1) /* 0.418680911 */, 18 }, + /* 6031 */ { MAD_F(0x06b34bd5) /* 0.418773491 */, 18 }, + + /* 6032 */ { MAD_F(0x06b3acea) /* 0.418866076 */, 18 }, + /* 6033 */ { MAD_F(0x06b40e00) /* 0.418958666 */, 18 }, + /* 6034 */ { MAD_F(0x06b46f18) /* 0.419051262 */, 18 }, + /* 6035 */ { MAD_F(0x06b4d031) /* 0.419143862 */, 18 }, + /* 6036 */ { MAD_F(0x06b5314c) /* 0.419236467 */, 18 }, + /* 6037 */ { MAD_F(0x06b59268) /* 0.419329078 */, 18 }, + /* 6038 */ { MAD_F(0x06b5f385) /* 0.419421694 */, 18 }, + /* 6039 */ { MAD_F(0x06b654a4) /* 0.419514314 */, 18 }, + /* 6040 */ { MAD_F(0x06b6b5c4) /* 0.419606940 */, 18 }, + /* 6041 */ { MAD_F(0x06b716e6) /* 0.419699571 */, 18 }, + /* 6042 */ { MAD_F(0x06b77808) /* 0.419792208 */, 18 }, + /* 6043 */ { MAD_F(0x06b7d92d) /* 0.419884849 */, 18 }, + /* 6044 */ { MAD_F(0x06b83a52) /* 0.419977495 */, 18 }, + /* 6045 */ { MAD_F(0x06b89b79) /* 0.420070147 */, 18 }, + /* 6046 */ { MAD_F(0x06b8fca1) /* 0.420162803 */, 18 }, + /* 6047 */ { MAD_F(0x06b95dcb) /* 0.420255465 */, 18 }, + + /* 6048 */ { MAD_F(0x06b9bef6) /* 0.420348132 */, 18 }, + /* 6049 */ { MAD_F(0x06ba2023) /* 0.420440803 */, 18 }, + /* 6050 */ { MAD_F(0x06ba8150) /* 0.420533481 */, 18 }, + /* 6051 */ { MAD_F(0x06bae280) /* 0.420626163 */, 18 }, + /* 6052 */ { MAD_F(0x06bb43b0) /* 0.420718850 */, 18 }, + /* 6053 */ { MAD_F(0x06bba4e2) /* 0.420811542 */, 18 }, + /* 6054 */ { MAD_F(0x06bc0615) /* 0.420904240 */, 18 }, + /* 6055 */ { MAD_F(0x06bc674a) /* 0.420996942 */, 18 }, + /* 6056 */ { MAD_F(0x06bcc880) /* 0.421089650 */, 18 }, + /* 6057 */ { MAD_F(0x06bd29b7) /* 0.421182362 */, 18 }, + /* 6058 */ { MAD_F(0x06bd8af0) /* 0.421275080 */, 18 }, + /* 6059 */ { MAD_F(0x06bdec2a) /* 0.421367803 */, 18 }, + /* 6060 */ { MAD_F(0x06be4d66) /* 0.421460531 */, 18 }, + /* 6061 */ { MAD_F(0x06beaea3) /* 0.421553264 */, 18 }, + /* 6062 */ { MAD_F(0x06bf0fe1) /* 0.421646003 */, 18 }, + /* 6063 */ { MAD_F(0x06bf7120) /* 0.421738746 */, 18 }, + + /* 6064 */ { MAD_F(0x06bfd261) /* 0.421831494 */, 18 }, + /* 6065 */ { MAD_F(0x06c033a4) /* 0.421924248 */, 18 }, + /* 6066 */ { MAD_F(0x06c094e7) /* 0.422017007 */, 18 }, + /* 6067 */ { MAD_F(0x06c0f62c) /* 0.422109770 */, 18 }, + /* 6068 */ { MAD_F(0x06c15773) /* 0.422202539 */, 18 }, + /* 6069 */ { MAD_F(0x06c1b8bb) /* 0.422295313 */, 18 }, + /* 6070 */ { MAD_F(0x06c21a04) /* 0.422388092 */, 18 }, + /* 6071 */ { MAD_F(0x06c27b4e) /* 0.422480876 */, 18 }, + /* 6072 */ { MAD_F(0x06c2dc9a) /* 0.422573665 */, 18 }, + /* 6073 */ { MAD_F(0x06c33de8) /* 0.422666460 */, 18 }, + /* 6074 */ { MAD_F(0x06c39f36) /* 0.422759259 */, 18 }, + /* 6075 */ { MAD_F(0x06c40086) /* 0.422852064 */, 18 }, + /* 6076 */ { MAD_F(0x06c461d8) /* 0.422944873 */, 18 }, + /* 6077 */ { MAD_F(0x06c4c32a) /* 0.423037688 */, 18 }, + /* 6078 */ { MAD_F(0x06c5247f) /* 0.423130508 */, 18 }, + /* 6079 */ { MAD_F(0x06c585d4) /* 0.423223333 */, 18 }, + + /* 6080 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 18 }, + /* 6081 */ { MAD_F(0x06c64883) /* 0.423408997 */, 18 }, + /* 6082 */ { MAD_F(0x06c6a9dd) /* 0.423501838 */, 18 }, + /* 6083 */ { MAD_F(0x06c70b38) /* 0.423594683 */, 18 }, + /* 6084 */ { MAD_F(0x06c76c94) /* 0.423687533 */, 18 }, + /* 6085 */ { MAD_F(0x06c7cdf2) /* 0.423780389 */, 18 }, + /* 6086 */ { MAD_F(0x06c82f51) /* 0.423873249 */, 18 }, + /* 6087 */ { MAD_F(0x06c890b1) /* 0.423966115 */, 18 }, + /* 6088 */ { MAD_F(0x06c8f213) /* 0.424058985 */, 18 }, + /* 6089 */ { MAD_F(0x06c95376) /* 0.424151861 */, 18 }, + /* 6090 */ { MAD_F(0x06c9b4da) /* 0.424244742 */, 18 }, + /* 6091 */ { MAD_F(0x06ca1640) /* 0.424337628 */, 18 }, + /* 6092 */ { MAD_F(0x06ca77a8) /* 0.424430519 */, 18 }, + /* 6093 */ { MAD_F(0x06cad910) /* 0.424523415 */, 18 }, + /* 6094 */ { MAD_F(0x06cb3a7a) /* 0.424616316 */, 18 }, + /* 6095 */ { MAD_F(0x06cb9be5) /* 0.424709222 */, 18 }, + + /* 6096 */ { MAD_F(0x06cbfd52) /* 0.424802133 */, 18 }, + /* 6097 */ { MAD_F(0x06cc5ec0) /* 0.424895050 */, 18 }, + /* 6098 */ { MAD_F(0x06ccc030) /* 0.424987971 */, 18 }, + /* 6099 */ { MAD_F(0x06cd21a0) /* 0.425080898 */, 18 }, + /* 6100 */ { MAD_F(0x06cd8313) /* 0.425173829 */, 18 }, + /* 6101 */ { MAD_F(0x06cde486) /* 0.425266766 */, 18 }, + /* 6102 */ { MAD_F(0x06ce45fb) /* 0.425359708 */, 18 }, + /* 6103 */ { MAD_F(0x06cea771) /* 0.425452655 */, 18 }, + /* 6104 */ { MAD_F(0x06cf08e9) /* 0.425545607 */, 18 }, + /* 6105 */ { MAD_F(0x06cf6a62) /* 0.425638564 */, 18 }, + /* 6106 */ { MAD_F(0x06cfcbdc) /* 0.425731526 */, 18 }, + /* 6107 */ { MAD_F(0x06d02d58) /* 0.425824493 */, 18 }, + /* 6108 */ { MAD_F(0x06d08ed5) /* 0.425917465 */, 18 }, + /* 6109 */ { MAD_F(0x06d0f053) /* 0.426010443 */, 18 }, + /* 6110 */ { MAD_F(0x06d151d3) /* 0.426103425 */, 18 }, + /* 6111 */ { MAD_F(0x06d1b354) /* 0.426196412 */, 18 }, + + /* 6112 */ { MAD_F(0x06d214d7) /* 0.426289405 */, 18 }, + /* 6113 */ { MAD_F(0x06d2765a) /* 0.426382403 */, 18 }, + /* 6114 */ { MAD_F(0x06d2d7e0) /* 0.426475405 */, 18 }, + /* 6115 */ { MAD_F(0x06d33966) /* 0.426568413 */, 18 }, + /* 6116 */ { MAD_F(0x06d39aee) /* 0.426661426 */, 18 }, + /* 6117 */ { MAD_F(0x06d3fc77) /* 0.426754444 */, 18 }, + /* 6118 */ { MAD_F(0x06d45e02) /* 0.426847467 */, 18 }, + /* 6119 */ { MAD_F(0x06d4bf8e) /* 0.426940495 */, 18 }, + /* 6120 */ { MAD_F(0x06d5211c) /* 0.427033528 */, 18 }, + /* 6121 */ { MAD_F(0x06d582aa) /* 0.427126566 */, 18 }, + /* 6122 */ { MAD_F(0x06d5e43a) /* 0.427219609 */, 18 }, + /* 6123 */ { MAD_F(0x06d645cc) /* 0.427312657 */, 18 }, + /* 6124 */ { MAD_F(0x06d6a75f) /* 0.427405711 */, 18 }, + /* 6125 */ { MAD_F(0x06d708f3) /* 0.427498769 */, 18 }, + /* 6126 */ { MAD_F(0x06d76a88) /* 0.427591833 */, 18 }, + /* 6127 */ { MAD_F(0x06d7cc1f) /* 0.427684901 */, 18 }, + + /* 6128 */ { MAD_F(0x06d82db8) /* 0.427777975 */, 18 }, + /* 6129 */ { MAD_F(0x06d88f51) /* 0.427871054 */, 18 }, + /* 6130 */ { MAD_F(0x06d8f0ec) /* 0.427964137 */, 18 }, + /* 6131 */ { MAD_F(0x06d95288) /* 0.428057226 */, 18 }, + /* 6132 */ { MAD_F(0x06d9b426) /* 0.428150320 */, 18 }, + /* 6133 */ { MAD_F(0x06da15c5) /* 0.428243419 */, 18 }, + /* 6134 */ { MAD_F(0x06da7766) /* 0.428336523 */, 18 }, + /* 6135 */ { MAD_F(0x06dad907) /* 0.428429632 */, 18 }, + /* 6136 */ { MAD_F(0x06db3aaa) /* 0.428522746 */, 18 }, + /* 6137 */ { MAD_F(0x06db9c4f) /* 0.428615865 */, 18 }, + /* 6138 */ { MAD_F(0x06dbfdf5) /* 0.428708989 */, 18 }, + /* 6139 */ { MAD_F(0x06dc5f9c) /* 0.428802119 */, 18 }, + /* 6140 */ { MAD_F(0x06dcc145) /* 0.428895253 */, 18 }, + /* 6141 */ { MAD_F(0x06dd22ee) /* 0.428988392 */, 18 }, + /* 6142 */ { MAD_F(0x06dd849a) /* 0.429081537 */, 18 }, + /* 6143 */ { MAD_F(0x06dde646) /* 0.429174686 */, 18 }, + + /* 6144 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 18 }, + /* 6145 */ { MAD_F(0x06dea9a4) /* 0.429361001 */, 18 }, + /* 6146 */ { MAD_F(0x06df0b54) /* 0.429454165 */, 18 }, + /* 6147 */ { MAD_F(0x06df6d06) /* 0.429547335 */, 18 }, + /* 6148 */ { MAD_F(0x06dfceba) /* 0.429640510 */, 18 }, + /* 6149 */ { MAD_F(0x06e0306f) /* 0.429733690 */, 18 }, + /* 6150 */ { MAD_F(0x06e09225) /* 0.429826874 */, 18 }, + /* 6151 */ { MAD_F(0x06e0f3dc) /* 0.429920064 */, 18 }, + /* 6152 */ { MAD_F(0x06e15595) /* 0.430013259 */, 18 }, + /* 6153 */ { MAD_F(0x06e1b74f) /* 0.430106459 */, 18 }, + /* 6154 */ { MAD_F(0x06e2190b) /* 0.430199664 */, 18 }, + /* 6155 */ { MAD_F(0x06e27ac8) /* 0.430292875 */, 18 }, + /* 6156 */ { MAD_F(0x06e2dc86) /* 0.430386090 */, 18 }, + /* 6157 */ { MAD_F(0x06e33e46) /* 0.430479310 */, 18 }, + /* 6158 */ { MAD_F(0x06e3a007) /* 0.430572535 */, 18 }, + /* 6159 */ { MAD_F(0x06e401c9) /* 0.430665765 */, 18 }, + + /* 6160 */ { MAD_F(0x06e4638d) /* 0.430759001 */, 18 }, + /* 6161 */ { MAD_F(0x06e4c552) /* 0.430852241 */, 18 }, + /* 6162 */ { MAD_F(0x06e52718) /* 0.430945487 */, 18 }, + /* 6163 */ { MAD_F(0x06e588e0) /* 0.431038737 */, 18 }, + /* 6164 */ { MAD_F(0x06e5eaa9) /* 0.431131993 */, 18 }, + /* 6165 */ { MAD_F(0x06e64c73) /* 0.431225253 */, 18 }, + /* 6166 */ { MAD_F(0x06e6ae3f) /* 0.431318519 */, 18 }, + /* 6167 */ { MAD_F(0x06e7100c) /* 0.431411790 */, 18 }, + /* 6168 */ { MAD_F(0x06e771db) /* 0.431505065 */, 18 }, + /* 6169 */ { MAD_F(0x06e7d3ab) /* 0.431598346 */, 18 }, + /* 6170 */ { MAD_F(0x06e8357c) /* 0.431691632 */, 18 }, + /* 6171 */ { MAD_F(0x06e8974e) /* 0.431784923 */, 18 }, + /* 6172 */ { MAD_F(0x06e8f922) /* 0.431878218 */, 18 }, + /* 6173 */ { MAD_F(0x06e95af8) /* 0.431971519 */, 18 }, + /* 6174 */ { MAD_F(0x06e9bcce) /* 0.432064825 */, 18 }, + /* 6175 */ { MAD_F(0x06ea1ea6) /* 0.432158136 */, 18 }, + + /* 6176 */ { MAD_F(0x06ea807f) /* 0.432251452 */, 18 }, + /* 6177 */ { MAD_F(0x06eae25a) /* 0.432344773 */, 18 }, + /* 6178 */ { MAD_F(0x06eb4436) /* 0.432438099 */, 18 }, + /* 6179 */ { MAD_F(0x06eba614) /* 0.432531431 */, 18 }, + /* 6180 */ { MAD_F(0x06ec07f2) /* 0.432624767 */, 18 }, + /* 6181 */ { MAD_F(0x06ec69d2) /* 0.432718108 */, 18 }, + /* 6182 */ { MAD_F(0x06eccbb4) /* 0.432811454 */, 18 }, + /* 6183 */ { MAD_F(0x06ed2d97) /* 0.432904805 */, 18 }, + /* 6184 */ { MAD_F(0x06ed8f7b) /* 0.432998162 */, 18 }, + /* 6185 */ { MAD_F(0x06edf160) /* 0.433091523 */, 18 }, + /* 6186 */ { MAD_F(0x06ee5347) /* 0.433184889 */, 18 }, + /* 6187 */ { MAD_F(0x06eeb52f) /* 0.433278261 */, 18 }, + /* 6188 */ { MAD_F(0x06ef1719) /* 0.433371637 */, 18 }, + /* 6189 */ { MAD_F(0x06ef7904) /* 0.433465019 */, 18 }, + /* 6190 */ { MAD_F(0x06efdaf0) /* 0.433558405 */, 18 }, + /* 6191 */ { MAD_F(0x06f03cde) /* 0.433651797 */, 18 }, + + /* 6192 */ { MAD_F(0x06f09ecc) /* 0.433745193 */, 18 }, + /* 6193 */ { MAD_F(0x06f100bd) /* 0.433838595 */, 18 }, + /* 6194 */ { MAD_F(0x06f162ae) /* 0.433932001 */, 18 }, + /* 6195 */ { MAD_F(0x06f1c4a1) /* 0.434025413 */, 18 }, + /* 6196 */ { MAD_F(0x06f22696) /* 0.434118830 */, 18 }, + /* 6197 */ { MAD_F(0x06f2888b) /* 0.434212251 */, 18 }, + /* 6198 */ { MAD_F(0x06f2ea82) /* 0.434305678 */, 18 }, + /* 6199 */ { MAD_F(0x06f34c7b) /* 0.434399110 */, 18 }, + /* 6200 */ { MAD_F(0x06f3ae75) /* 0.434492546 */, 18 }, + /* 6201 */ { MAD_F(0x06f41070) /* 0.434585988 */, 18 }, + /* 6202 */ { MAD_F(0x06f4726c) /* 0.434679435 */, 18 }, + /* 6203 */ { MAD_F(0x06f4d46a) /* 0.434772887 */, 18 }, + /* 6204 */ { MAD_F(0x06f53669) /* 0.434866344 */, 18 }, + /* 6205 */ { MAD_F(0x06f59869) /* 0.434959806 */, 18 }, + /* 6206 */ { MAD_F(0x06f5fa6b) /* 0.435053272 */, 18 }, + /* 6207 */ { MAD_F(0x06f65c6e) /* 0.435146744 */, 18 }, + + /* 6208 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 18 }, + /* 6209 */ { MAD_F(0x06f72079) /* 0.435333703 */, 18 }, + /* 6210 */ { MAD_F(0x06f78280) /* 0.435427190 */, 18 }, + /* 6211 */ { MAD_F(0x06f7e489) /* 0.435520682 */, 18 }, + /* 6212 */ { MAD_F(0x06f84693) /* 0.435614179 */, 18 }, + /* 6213 */ { MAD_F(0x06f8a89e) /* 0.435707681 */, 18 }, + /* 6214 */ { MAD_F(0x06f90aaa) /* 0.435801188 */, 18 }, + /* 6215 */ { MAD_F(0x06f96cb8) /* 0.435894700 */, 18 }, + /* 6216 */ { MAD_F(0x06f9cec8) /* 0.435988217 */, 18 }, + /* 6217 */ { MAD_F(0x06fa30d8) /* 0.436081739 */, 18 }, + /* 6218 */ { MAD_F(0x06fa92ea) /* 0.436175266 */, 18 }, + /* 6219 */ { MAD_F(0x06faf4fe) /* 0.436268799 */, 18 }, + /* 6220 */ { MAD_F(0x06fb5712) /* 0.436362336 */, 18 }, + /* 6221 */ { MAD_F(0x06fbb928) /* 0.436455878 */, 18 }, + /* 6222 */ { MAD_F(0x06fc1b40) /* 0.436549425 */, 18 }, + /* 6223 */ { MAD_F(0x06fc7d58) /* 0.436642977 */, 18 }, + + /* 6224 */ { MAD_F(0x06fcdf72) /* 0.436736534 */, 18 }, + /* 6225 */ { MAD_F(0x06fd418e) /* 0.436830096 */, 18 }, + /* 6226 */ { MAD_F(0x06fda3ab) /* 0.436923664 */, 18 }, + /* 6227 */ { MAD_F(0x06fe05c9) /* 0.437017236 */, 18 }, + /* 6228 */ { MAD_F(0x06fe67e8) /* 0.437110813 */, 18 }, + /* 6229 */ { MAD_F(0x06feca09) /* 0.437204395 */, 18 }, + /* 6230 */ { MAD_F(0x06ff2c2b) /* 0.437297982 */, 18 }, + /* 6231 */ { MAD_F(0x06ff8e4f) /* 0.437391575 */, 18 }, + /* 6232 */ { MAD_F(0x06fff073) /* 0.437485172 */, 18 }, + /* 6233 */ { MAD_F(0x0700529a) /* 0.437578774 */, 18 }, + /* 6234 */ { MAD_F(0x0700b4c1) /* 0.437672381 */, 18 }, + /* 6235 */ { MAD_F(0x070116ea) /* 0.437765994 */, 18 }, + /* 6236 */ { MAD_F(0x07017914) /* 0.437859611 */, 18 }, + /* 6237 */ { MAD_F(0x0701db40) /* 0.437953233 */, 18 }, + /* 6238 */ { MAD_F(0x07023d6c) /* 0.438046860 */, 18 }, + /* 6239 */ { MAD_F(0x07029f9b) /* 0.438140493 */, 18 }, + + /* 6240 */ { MAD_F(0x070301ca) /* 0.438234130 */, 18 }, + /* 6241 */ { MAD_F(0x070363fb) /* 0.438327772 */, 18 }, + /* 6242 */ { MAD_F(0x0703c62d) /* 0.438421419 */, 18 }, + /* 6243 */ { MAD_F(0x07042861) /* 0.438515072 */, 18 }, + /* 6244 */ { MAD_F(0x07048a96) /* 0.438608729 */, 18 }, + /* 6245 */ { MAD_F(0x0704eccc) /* 0.438702391 */, 18 }, + /* 6246 */ { MAD_F(0x07054f04) /* 0.438796059 */, 18 }, + /* 6247 */ { MAD_F(0x0705b13d) /* 0.438889731 */, 18 }, + /* 6248 */ { MAD_F(0x07061377) /* 0.438983408 */, 18 }, + /* 6249 */ { MAD_F(0x070675b3) /* 0.439077090 */, 18 }, + /* 6250 */ { MAD_F(0x0706d7f0) /* 0.439170778 */, 18 }, + /* 6251 */ { MAD_F(0x07073a2e) /* 0.439264470 */, 18 }, + /* 6252 */ { MAD_F(0x07079c6e) /* 0.439358167 */, 18 }, + /* 6253 */ { MAD_F(0x0707feaf) /* 0.439451869 */, 18 }, + /* 6254 */ { MAD_F(0x070860f1) /* 0.439545577 */, 18 }, + /* 6255 */ { MAD_F(0x0708c335) /* 0.439639289 */, 18 }, + + /* 6256 */ { MAD_F(0x0709257a) /* 0.439733006 */, 18 }, + /* 6257 */ { MAD_F(0x070987c0) /* 0.439826728 */, 18 }, + /* 6258 */ { MAD_F(0x0709ea08) /* 0.439920456 */, 18 }, + /* 6259 */ { MAD_F(0x070a4c51) /* 0.440014188 */, 18 }, + /* 6260 */ { MAD_F(0x070aae9b) /* 0.440107925 */, 18 }, + /* 6261 */ { MAD_F(0x070b10e7) /* 0.440201667 */, 18 }, + /* 6262 */ { MAD_F(0x070b7334) /* 0.440295414 */, 18 }, + /* 6263 */ { MAD_F(0x070bd583) /* 0.440389167 */, 18 }, + /* 6264 */ { MAD_F(0x070c37d2) /* 0.440482924 */, 18 }, + /* 6265 */ { MAD_F(0x070c9a23) /* 0.440576686 */, 18 }, + /* 6266 */ { MAD_F(0x070cfc76) /* 0.440670453 */, 18 }, + /* 6267 */ { MAD_F(0x070d5eca) /* 0.440764225 */, 18 }, + /* 6268 */ { MAD_F(0x070dc11f) /* 0.440858002 */, 18 }, + /* 6269 */ { MAD_F(0x070e2375) /* 0.440951784 */, 18 }, + /* 6270 */ { MAD_F(0x070e85cd) /* 0.441045572 */, 18 }, + /* 6271 */ { MAD_F(0x070ee826) /* 0.441139364 */, 18 }, + + /* 6272 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 18 }, + /* 6273 */ { MAD_F(0x070facdc) /* 0.441326963 */, 18 }, + /* 6274 */ { MAD_F(0x07100f39) /* 0.441420770 */, 18 }, + /* 6275 */ { MAD_F(0x07107198) /* 0.441514582 */, 18 }, + /* 6276 */ { MAD_F(0x0710d3f8) /* 0.441608399 */, 18 }, + /* 6277 */ { MAD_F(0x07113659) /* 0.441702221 */, 18 }, + /* 6278 */ { MAD_F(0x071198bb) /* 0.441796048 */, 18 }, + /* 6279 */ { MAD_F(0x0711fb1f) /* 0.441889880 */, 18 }, + /* 6280 */ { MAD_F(0x07125d84) /* 0.441983717 */, 18 }, + /* 6281 */ { MAD_F(0x0712bfeb) /* 0.442077559 */, 18 }, + /* 6282 */ { MAD_F(0x07132253) /* 0.442171406 */, 18 }, + /* 6283 */ { MAD_F(0x071384bc) /* 0.442265257 */, 18 }, + /* 6284 */ { MAD_F(0x0713e726) /* 0.442359114 */, 18 }, + /* 6285 */ { MAD_F(0x07144992) /* 0.442452976 */, 18 }, + /* 6286 */ { MAD_F(0x0714abff) /* 0.442546843 */, 18 }, + /* 6287 */ { MAD_F(0x07150e6e) /* 0.442640715 */, 18 }, + + /* 6288 */ { MAD_F(0x071570de) /* 0.442734592 */, 18 }, + /* 6289 */ { MAD_F(0x0715d34f) /* 0.442828473 */, 18 }, + /* 6290 */ { MAD_F(0x071635c1) /* 0.442922360 */, 18 }, + /* 6291 */ { MAD_F(0x07169835) /* 0.443016252 */, 18 }, + /* 6292 */ { MAD_F(0x0716faaa) /* 0.443110148 */, 18 }, + /* 6293 */ { MAD_F(0x07175d21) /* 0.443204050 */, 18 }, + /* 6294 */ { MAD_F(0x0717bf99) /* 0.443297957 */, 18 }, + /* 6295 */ { MAD_F(0x07182212) /* 0.443391868 */, 18 }, + /* 6296 */ { MAD_F(0x0718848d) /* 0.443485785 */, 18 }, + /* 6297 */ { MAD_F(0x0718e709) /* 0.443579706 */, 18 }, + /* 6298 */ { MAD_F(0x07194986) /* 0.443673633 */, 18 }, + /* 6299 */ { MAD_F(0x0719ac04) /* 0.443767564 */, 18 }, + /* 6300 */ { MAD_F(0x071a0e84) /* 0.443861501 */, 18 }, + /* 6301 */ { MAD_F(0x071a7105) /* 0.443955442 */, 18 }, + /* 6302 */ { MAD_F(0x071ad388) /* 0.444049389 */, 18 }, + /* 6303 */ { MAD_F(0x071b360c) /* 0.444143340 */, 18 }, + + /* 6304 */ { MAD_F(0x071b9891) /* 0.444237296 */, 18 }, + /* 6305 */ { MAD_F(0x071bfb18) /* 0.444331258 */, 18 }, + /* 6306 */ { MAD_F(0x071c5d9f) /* 0.444425224 */, 18 }, + /* 6307 */ { MAD_F(0x071cc029) /* 0.444519195 */, 18 }, + /* 6308 */ { MAD_F(0x071d22b3) /* 0.444613171 */, 18 }, + /* 6309 */ { MAD_F(0x071d853f) /* 0.444707153 */, 18 }, + /* 6310 */ { MAD_F(0x071de7cc) /* 0.444801139 */, 18 }, + /* 6311 */ { MAD_F(0x071e4a5b) /* 0.444895130 */, 18 }, + /* 6312 */ { MAD_F(0x071eaceb) /* 0.444989126 */, 18 }, + /* 6313 */ { MAD_F(0x071f0f7c) /* 0.445083127 */, 18 }, + /* 6314 */ { MAD_F(0x071f720e) /* 0.445177133 */, 18 }, + /* 6315 */ { MAD_F(0x071fd4a2) /* 0.445271144 */, 18 }, + /* 6316 */ { MAD_F(0x07203737) /* 0.445365160 */, 18 }, + /* 6317 */ { MAD_F(0x072099ce) /* 0.445459181 */, 18 }, + /* 6318 */ { MAD_F(0x0720fc66) /* 0.445553206 */, 18 }, + /* 6319 */ { MAD_F(0x07215eff) /* 0.445647237 */, 18 }, + + /* 6320 */ { MAD_F(0x0721c19a) /* 0.445741273 */, 18 }, + /* 6321 */ { MAD_F(0x07222436) /* 0.445835314 */, 18 }, + /* 6322 */ { MAD_F(0x072286d3) /* 0.445929359 */, 18 }, + /* 6323 */ { MAD_F(0x0722e971) /* 0.446023410 */, 18 }, + /* 6324 */ { MAD_F(0x07234c11) /* 0.446117466 */, 18 }, + /* 6325 */ { MAD_F(0x0723aeb2) /* 0.446211526 */, 18 }, + /* 6326 */ { MAD_F(0x07241155) /* 0.446305592 */, 18 }, + /* 6327 */ { MAD_F(0x072473f9) /* 0.446399662 */, 18 }, + /* 6328 */ { MAD_F(0x0724d69e) /* 0.446493738 */, 18 }, + /* 6329 */ { MAD_F(0x07253944) /* 0.446587818 */, 18 }, + /* 6330 */ { MAD_F(0x07259bec) /* 0.446681903 */, 18 }, + /* 6331 */ { MAD_F(0x0725fe95) /* 0.446775994 */, 18 }, + /* 6332 */ { MAD_F(0x07266140) /* 0.446870089 */, 18 }, + /* 6333 */ { MAD_F(0x0726c3ec) /* 0.446964189 */, 18 }, + /* 6334 */ { MAD_F(0x07272699) /* 0.447058294 */, 18 }, + /* 6335 */ { MAD_F(0x07278947) /* 0.447152404 */, 18 }, + + /* 6336 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 18 }, + /* 6337 */ { MAD_F(0x07284ea8) /* 0.447340639 */, 18 }, + /* 6338 */ { MAD_F(0x0728b15b) /* 0.447434764 */, 18 }, + /* 6339 */ { MAD_F(0x0729140f) /* 0.447528894 */, 18 }, + /* 6340 */ { MAD_F(0x072976c4) /* 0.447623029 */, 18 }, + /* 6341 */ { MAD_F(0x0729d97a) /* 0.447717169 */, 18 }, + /* 6342 */ { MAD_F(0x072a3c32) /* 0.447811314 */, 18 }, + /* 6343 */ { MAD_F(0x072a9eeb) /* 0.447905463 */, 18 }, + /* 6344 */ { MAD_F(0x072b01a6) /* 0.447999618 */, 18 }, + /* 6345 */ { MAD_F(0x072b6461) /* 0.448093778 */, 18 }, + /* 6346 */ { MAD_F(0x072bc71e) /* 0.448187942 */, 18 }, + /* 6347 */ { MAD_F(0x072c29dd) /* 0.448282112 */, 18 }, + /* 6348 */ { MAD_F(0x072c8c9d) /* 0.448376286 */, 18 }, + /* 6349 */ { MAD_F(0x072cef5e) /* 0.448470466 */, 18 }, + /* 6350 */ { MAD_F(0x072d5220) /* 0.448564650 */, 18 }, + /* 6351 */ { MAD_F(0x072db4e4) /* 0.448658839 */, 18 }, + + /* 6352 */ { MAD_F(0x072e17a9) /* 0.448753033 */, 18 }, + /* 6353 */ { MAD_F(0x072e7a6f) /* 0.448847233 */, 18 }, + /* 6354 */ { MAD_F(0x072edd37) /* 0.448941437 */, 18 }, + /* 6355 */ { MAD_F(0x072f4000) /* 0.449035646 */, 18 }, + /* 6356 */ { MAD_F(0x072fa2ca) /* 0.449129860 */, 18 }, + /* 6357 */ { MAD_F(0x07300596) /* 0.449224079 */, 18 }, + /* 6358 */ { MAD_F(0x07306863) /* 0.449318303 */, 18 }, + /* 6359 */ { MAD_F(0x0730cb32) /* 0.449412531 */, 18 }, + /* 6360 */ { MAD_F(0x07312e01) /* 0.449506765 */, 18 }, + /* 6361 */ { MAD_F(0x073190d2) /* 0.449601004 */, 18 }, + /* 6362 */ { MAD_F(0x0731f3a5) /* 0.449695247 */, 18 }, + /* 6363 */ { MAD_F(0x07325678) /* 0.449789496 */, 18 }, + /* 6364 */ { MAD_F(0x0732b94d) /* 0.449883749 */, 18 }, + /* 6365 */ { MAD_F(0x07331c23) /* 0.449978008 */, 18 }, + /* 6366 */ { MAD_F(0x07337efb) /* 0.450072271 */, 18 }, + /* 6367 */ { MAD_F(0x0733e1d4) /* 0.450166540 */, 18 }, + + /* 6368 */ { MAD_F(0x073444ae) /* 0.450260813 */, 18 }, + /* 6369 */ { MAD_F(0x0734a78a) /* 0.450355091 */, 18 }, + /* 6370 */ { MAD_F(0x07350a67) /* 0.450449374 */, 18 }, + /* 6371 */ { MAD_F(0x07356d45) /* 0.450543662 */, 18 }, + /* 6372 */ { MAD_F(0x0735d025) /* 0.450637955 */, 18 }, + /* 6373 */ { MAD_F(0x07363306) /* 0.450732253 */, 18 }, + /* 6374 */ { MAD_F(0x073695e8) /* 0.450826556 */, 18 }, + /* 6375 */ { MAD_F(0x0736f8cb) /* 0.450920864 */, 18 }, + /* 6376 */ { MAD_F(0x07375bb0) /* 0.451015176 */, 18 }, + /* 6377 */ { MAD_F(0x0737be96) /* 0.451109494 */, 18 }, + /* 6378 */ { MAD_F(0x0738217e) /* 0.451203817 */, 18 }, + /* 6379 */ { MAD_F(0x07388467) /* 0.451298144 */, 18 }, + /* 6380 */ { MAD_F(0x0738e751) /* 0.451392477 */, 18 }, + /* 6381 */ { MAD_F(0x07394a3d) /* 0.451486814 */, 18 }, + /* 6382 */ { MAD_F(0x0739ad29) /* 0.451581156 */, 18 }, + /* 6383 */ { MAD_F(0x073a1017) /* 0.451675503 */, 18 }, + + /* 6384 */ { MAD_F(0x073a7307) /* 0.451769856 */, 18 }, + /* 6385 */ { MAD_F(0x073ad5f8) /* 0.451864213 */, 18 }, + /* 6386 */ { MAD_F(0x073b38ea) /* 0.451958575 */, 18 }, + /* 6387 */ { MAD_F(0x073b9bdd) /* 0.452052942 */, 18 }, + /* 6388 */ { MAD_F(0x073bfed2) /* 0.452147313 */, 18 }, + /* 6389 */ { MAD_F(0x073c61c8) /* 0.452241690 */, 18 }, + /* 6390 */ { MAD_F(0x073cc4bf) /* 0.452336072 */, 18 }, + /* 6391 */ { MAD_F(0x073d27b8) /* 0.452430458 */, 18 }, + /* 6392 */ { MAD_F(0x073d8ab2) /* 0.452524850 */, 18 }, + /* 6393 */ { MAD_F(0x073dedae) /* 0.452619246 */, 18 }, + /* 6394 */ { MAD_F(0x073e50aa) /* 0.452713648 */, 18 }, + /* 6395 */ { MAD_F(0x073eb3a8) /* 0.452808054 */, 18 }, + /* 6396 */ { MAD_F(0x073f16a8) /* 0.452902465 */, 18 }, + /* 6397 */ { MAD_F(0x073f79a8) /* 0.452996882 */, 18 }, + /* 6398 */ { MAD_F(0x073fdcaa) /* 0.453091303 */, 18 }, + /* 6399 */ { MAD_F(0x07403fad) /* 0.453185729 */, 18 }, + + /* 6400 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 18 }, + /* 6401 */ { MAD_F(0x074105b8) /* 0.453374595 */, 18 }, + /* 6402 */ { MAD_F(0x074168bf) /* 0.453469036 */, 18 }, + /* 6403 */ { MAD_F(0x0741cbc8) /* 0.453563482 */, 18 }, + /* 6404 */ { MAD_F(0x07422ed2) /* 0.453657932 */, 18 }, + /* 6405 */ { MAD_F(0x074291dd) /* 0.453752388 */, 18 }, + /* 6406 */ { MAD_F(0x0742f4e9) /* 0.453846848 */, 18 }, + /* 6407 */ { MAD_F(0x074357f7) /* 0.453941314 */, 18 }, + /* 6408 */ { MAD_F(0x0743bb06) /* 0.454035784 */, 18 }, + /* 6409 */ { MAD_F(0x07441e17) /* 0.454130259 */, 18 }, + /* 6410 */ { MAD_F(0x07448129) /* 0.454224739 */, 18 }, + /* 6411 */ { MAD_F(0x0744e43c) /* 0.454319224 */, 18 }, + /* 6412 */ { MAD_F(0x07454750) /* 0.454413714 */, 18 }, + /* 6413 */ { MAD_F(0x0745aa66) /* 0.454508209 */, 18 }, + /* 6414 */ { MAD_F(0x07460d7d) /* 0.454602708 */, 18 }, + /* 6415 */ { MAD_F(0x07467095) /* 0.454697213 */, 18 }, + + /* 6416 */ { MAD_F(0x0746d3af) /* 0.454791723 */, 18 }, + /* 6417 */ { MAD_F(0x074736ca) /* 0.454886237 */, 18 }, + /* 6418 */ { MAD_F(0x074799e7) /* 0.454980756 */, 18 }, + /* 6419 */ { MAD_F(0x0747fd04) /* 0.455075281 */, 18 }, + /* 6420 */ { MAD_F(0x07486023) /* 0.455169810 */, 18 }, + /* 6421 */ { MAD_F(0x0748c344) /* 0.455264344 */, 18 }, + /* 6422 */ { MAD_F(0x07492665) /* 0.455358883 */, 18 }, + /* 6423 */ { MAD_F(0x07498988) /* 0.455453427 */, 18 }, + /* 6424 */ { MAD_F(0x0749ecac) /* 0.455547976 */, 18 }, + /* 6425 */ { MAD_F(0x074a4fd2) /* 0.455642529 */, 18 }, + /* 6426 */ { MAD_F(0x074ab2f9) /* 0.455737088 */, 18 }, + /* 6427 */ { MAD_F(0x074b1621) /* 0.455831652 */, 18 }, + /* 6428 */ { MAD_F(0x074b794b) /* 0.455926220 */, 18 }, + /* 6429 */ { MAD_F(0x074bdc75) /* 0.456020793 */, 18 }, + /* 6430 */ { MAD_F(0x074c3fa1) /* 0.456115372 */, 18 }, + /* 6431 */ { MAD_F(0x074ca2cf) /* 0.456209955 */, 18 }, + + /* 6432 */ { MAD_F(0x074d05fe) /* 0.456304543 */, 18 }, + /* 6433 */ { MAD_F(0x074d692e) /* 0.456399136 */, 18 }, + /* 6434 */ { MAD_F(0x074dcc5f) /* 0.456493733 */, 18 }, + /* 6435 */ { MAD_F(0x074e2f92) /* 0.456588336 */, 18 }, + /* 6436 */ { MAD_F(0x074e92c6) /* 0.456682944 */, 18 }, + /* 6437 */ { MAD_F(0x074ef5fb) /* 0.456777556 */, 18 }, + /* 6438 */ { MAD_F(0x074f5932) /* 0.456872174 */, 18 }, + /* 6439 */ { MAD_F(0x074fbc6a) /* 0.456966796 */, 18 }, + /* 6440 */ { MAD_F(0x07501fa3) /* 0.457061423 */, 18 }, + /* 6441 */ { MAD_F(0x075082de) /* 0.457156056 */, 18 }, + /* 6442 */ { MAD_F(0x0750e61a) /* 0.457250693 */, 18 }, + /* 6443 */ { MAD_F(0x07514957) /* 0.457345335 */, 18 }, + /* 6444 */ { MAD_F(0x0751ac96) /* 0.457439981 */, 18 }, + /* 6445 */ { MAD_F(0x07520fd6) /* 0.457534633 */, 18 }, + /* 6446 */ { MAD_F(0x07527317) /* 0.457629290 */, 18 }, + /* 6447 */ { MAD_F(0x0752d659) /* 0.457723951 */, 18 }, + + /* 6448 */ { MAD_F(0x0753399d) /* 0.457818618 */, 18 }, + /* 6449 */ { MAD_F(0x07539ce2) /* 0.457913289 */, 18 }, + /* 6450 */ { MAD_F(0x07540029) /* 0.458007965 */, 18 }, + /* 6451 */ { MAD_F(0x07546371) /* 0.458102646 */, 18 }, + /* 6452 */ { MAD_F(0x0754c6ba) /* 0.458197332 */, 18 }, + /* 6453 */ { MAD_F(0x07552a04) /* 0.458292023 */, 18 }, + /* 6454 */ { MAD_F(0x07558d50) /* 0.458386719 */, 18 }, + /* 6455 */ { MAD_F(0x0755f09d) /* 0.458481420 */, 18 }, + /* 6456 */ { MAD_F(0x075653eb) /* 0.458576125 */, 18 }, + /* 6457 */ { MAD_F(0x0756b73b) /* 0.458670836 */, 18 }, + /* 6458 */ { MAD_F(0x07571a8c) /* 0.458765551 */, 18 }, + /* 6459 */ { MAD_F(0x07577dde) /* 0.458860271 */, 18 }, + /* 6460 */ { MAD_F(0x0757e131) /* 0.458954996 */, 18 }, + /* 6461 */ { MAD_F(0x07584486) /* 0.459049726 */, 18 }, + /* 6462 */ { MAD_F(0x0758a7dd) /* 0.459144461 */, 18 }, + /* 6463 */ { MAD_F(0x07590b34) /* 0.459239201 */, 18 }, + + /* 6464 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 18 }, + /* 6465 */ { MAD_F(0x0759d1e7) /* 0.459428695 */, 18 }, + /* 6466 */ { MAD_F(0x075a3542) /* 0.459523450 */, 18 }, + /* 6467 */ { MAD_F(0x075a989f) /* 0.459618209 */, 18 }, + /* 6468 */ { MAD_F(0x075afbfd) /* 0.459712973 */, 18 }, + /* 6469 */ { MAD_F(0x075b5f5d) /* 0.459807742 */, 18 }, + /* 6470 */ { MAD_F(0x075bc2bd) /* 0.459902516 */, 18 }, + /* 6471 */ { MAD_F(0x075c261f) /* 0.459997295 */, 18 }, + /* 6472 */ { MAD_F(0x075c8983) /* 0.460092079 */, 18 }, + /* 6473 */ { MAD_F(0x075cece7) /* 0.460186867 */, 18 }, + /* 6474 */ { MAD_F(0x075d504d) /* 0.460281661 */, 18 }, + /* 6475 */ { MAD_F(0x075db3b5) /* 0.460376459 */, 18 }, + /* 6476 */ { MAD_F(0x075e171d) /* 0.460471262 */, 18 }, + /* 6477 */ { MAD_F(0x075e7a87) /* 0.460566071 */, 18 }, + /* 6478 */ { MAD_F(0x075eddf2) /* 0.460660884 */, 18 }, + /* 6479 */ { MAD_F(0x075f415f) /* 0.460755701 */, 18 }, + + /* 6480 */ { MAD_F(0x075fa4cc) /* 0.460850524 */, 18 }, + /* 6481 */ { MAD_F(0x0760083b) /* 0.460945352 */, 18 }, + /* 6482 */ { MAD_F(0x07606bac) /* 0.461040184 */, 18 }, + /* 6483 */ { MAD_F(0x0760cf1e) /* 0.461135022 */, 18 }, + /* 6484 */ { MAD_F(0x07613291) /* 0.461229864 */, 18 }, + /* 6485 */ { MAD_F(0x07619605) /* 0.461324711 */, 18 }, + /* 6486 */ { MAD_F(0x0761f97b) /* 0.461419563 */, 18 }, + /* 6487 */ { MAD_F(0x07625cf2) /* 0.461514420 */, 18 }, + /* 6488 */ { MAD_F(0x0762c06a) /* 0.461609282 */, 18 }, + /* 6489 */ { MAD_F(0x076323e3) /* 0.461704149 */, 18 }, + /* 6490 */ { MAD_F(0x0763875e) /* 0.461799020 */, 18 }, + /* 6491 */ { MAD_F(0x0763eadb) /* 0.461893897 */, 18 }, + /* 6492 */ { MAD_F(0x07644e58) /* 0.461988778 */, 18 }, + /* 6493 */ { MAD_F(0x0764b1d7) /* 0.462083664 */, 18 }, + /* 6494 */ { MAD_F(0x07651557) /* 0.462178555 */, 18 }, + /* 6495 */ { MAD_F(0x076578d8) /* 0.462273451 */, 18 }, + + /* 6496 */ { MAD_F(0x0765dc5b) /* 0.462368352 */, 18 }, + /* 6497 */ { MAD_F(0x07663fdf) /* 0.462463257 */, 18 }, + /* 6498 */ { MAD_F(0x0766a364) /* 0.462558168 */, 18 }, + /* 6499 */ { MAD_F(0x076706eb) /* 0.462653083 */, 18 }, + /* 6500 */ { MAD_F(0x07676a73) /* 0.462748003 */, 18 }, + /* 6501 */ { MAD_F(0x0767cdfc) /* 0.462842928 */, 18 }, + /* 6502 */ { MAD_F(0x07683187) /* 0.462937858 */, 18 }, + /* 6503 */ { MAD_F(0x07689513) /* 0.463032793 */, 18 }, + /* 6504 */ { MAD_F(0x0768f8a0) /* 0.463127733 */, 18 }, + /* 6505 */ { MAD_F(0x07695c2e) /* 0.463222678 */, 18 }, + /* 6506 */ { MAD_F(0x0769bfbe) /* 0.463317627 */, 18 }, + /* 6507 */ { MAD_F(0x076a234f) /* 0.463412581 */, 18 }, + /* 6508 */ { MAD_F(0x076a86e2) /* 0.463507540 */, 18 }, + /* 6509 */ { MAD_F(0x076aea75) /* 0.463602504 */, 18 }, + /* 6510 */ { MAD_F(0x076b4e0a) /* 0.463697473 */, 18 }, + /* 6511 */ { MAD_F(0x076bb1a1) /* 0.463792447 */, 18 }, + + /* 6512 */ { MAD_F(0x076c1538) /* 0.463887426 */, 18 }, + /* 6513 */ { MAD_F(0x076c78d1) /* 0.463982409 */, 18 }, + /* 6514 */ { MAD_F(0x076cdc6c) /* 0.464077398 */, 18 }, + /* 6515 */ { MAD_F(0x076d4007) /* 0.464172391 */, 18 }, + /* 6516 */ { MAD_F(0x076da3a4) /* 0.464267389 */, 18 }, + /* 6517 */ { MAD_F(0x076e0742) /* 0.464362392 */, 18 }, + /* 6518 */ { MAD_F(0x076e6ae2) /* 0.464457399 */, 18 }, + /* 6519 */ { MAD_F(0x076ece82) /* 0.464552412 */, 18 }, + /* 6520 */ { MAD_F(0x076f3224) /* 0.464647430 */, 18 }, + /* 6521 */ { MAD_F(0x076f95c8) /* 0.464742452 */, 18 }, + /* 6522 */ { MAD_F(0x076ff96c) /* 0.464837479 */, 18 }, + /* 6523 */ { MAD_F(0x07705d12) /* 0.464932511 */, 18 }, + /* 6524 */ { MAD_F(0x0770c0ba) /* 0.465027548 */, 18 }, + /* 6525 */ { MAD_F(0x07712462) /* 0.465122590 */, 18 }, + /* 6526 */ { MAD_F(0x0771880c) /* 0.465217637 */, 18 }, + /* 6527 */ { MAD_F(0x0771ebb7) /* 0.465312688 */, 18 }, + + /* 6528 */ { MAD_F(0x07724f64) /* 0.465407744 */, 18 }, + /* 6529 */ { MAD_F(0x0772b312) /* 0.465502806 */, 18 }, + /* 6530 */ { MAD_F(0x077316c1) /* 0.465597872 */, 18 }, + /* 6531 */ { MAD_F(0x07737a71) /* 0.465692943 */, 18 }, + /* 6532 */ { MAD_F(0x0773de23) /* 0.465788018 */, 18 }, + /* 6533 */ { MAD_F(0x077441d6) /* 0.465883099 */, 18 }, + /* 6534 */ { MAD_F(0x0774a58a) /* 0.465978184 */, 18 }, + /* 6535 */ { MAD_F(0x07750940) /* 0.466073275 */, 18 }, + /* 6536 */ { MAD_F(0x07756cf7) /* 0.466168370 */, 18 }, + /* 6537 */ { MAD_F(0x0775d0af) /* 0.466263470 */, 18 }, + /* 6538 */ { MAD_F(0x07763468) /* 0.466358575 */, 18 }, + /* 6539 */ { MAD_F(0x07769823) /* 0.466453684 */, 18 }, + /* 6540 */ { MAD_F(0x0776fbdf) /* 0.466548799 */, 18 }, + /* 6541 */ { MAD_F(0x07775f9d) /* 0.466643918 */, 18 }, + /* 6542 */ { MAD_F(0x0777c35c) /* 0.466739043 */, 18 }, + /* 6543 */ { MAD_F(0x0778271c) /* 0.466834172 */, 18 }, + + /* 6544 */ { MAD_F(0x07788add) /* 0.466929306 */, 18 }, + /* 6545 */ { MAD_F(0x0778ee9f) /* 0.467024445 */, 18 }, + /* 6546 */ { MAD_F(0x07795263) /* 0.467119588 */, 18 }, + /* 6547 */ { MAD_F(0x0779b629) /* 0.467214737 */, 18 }, + /* 6548 */ { MAD_F(0x077a19ef) /* 0.467309890 */, 18 }, + /* 6549 */ { MAD_F(0x077a7db7) /* 0.467405048 */, 18 }, + /* 6550 */ { MAD_F(0x077ae180) /* 0.467500211 */, 18 }, + /* 6551 */ { MAD_F(0x077b454b) /* 0.467595379 */, 18 }, + /* 6552 */ { MAD_F(0x077ba916) /* 0.467690552 */, 18 }, + /* 6553 */ { MAD_F(0x077c0ce3) /* 0.467785729 */, 18 }, + /* 6554 */ { MAD_F(0x077c70b2) /* 0.467880912 */, 18 }, + /* 6555 */ { MAD_F(0x077cd481) /* 0.467976099 */, 18 }, + /* 6556 */ { MAD_F(0x077d3852) /* 0.468071291 */, 18 }, + /* 6557 */ { MAD_F(0x077d9c24) /* 0.468166488 */, 18 }, + /* 6558 */ { MAD_F(0x077dfff8) /* 0.468261690 */, 18 }, + /* 6559 */ { MAD_F(0x077e63cd) /* 0.468356896 */, 18 }, + + /* 6560 */ { MAD_F(0x077ec7a3) /* 0.468452108 */, 18 }, + /* 6561 */ { MAD_F(0x077f2b7a) /* 0.468547324 */, 18 }, + /* 6562 */ { MAD_F(0x077f8f53) /* 0.468642545 */, 18 }, + /* 6563 */ { MAD_F(0x077ff32d) /* 0.468737771 */, 18 }, + /* 6564 */ { MAD_F(0x07805708) /* 0.468833002 */, 18 }, + /* 6565 */ { MAD_F(0x0780bae5) /* 0.468928237 */, 18 }, + /* 6566 */ { MAD_F(0x07811ec3) /* 0.469023478 */, 18 }, + /* 6567 */ { MAD_F(0x078182a2) /* 0.469118723 */, 18 }, + /* 6568 */ { MAD_F(0x0781e683) /* 0.469213973 */, 18 }, + /* 6569 */ { MAD_F(0x07824a64) /* 0.469309228 */, 18 }, + /* 6570 */ { MAD_F(0x0782ae47) /* 0.469404488 */, 18 }, + /* 6571 */ { MAD_F(0x0783122c) /* 0.469499752 */, 18 }, + /* 6572 */ { MAD_F(0x07837612) /* 0.469595022 */, 18 }, + /* 6573 */ { MAD_F(0x0783d9f9) /* 0.469690296 */, 18 }, + /* 6574 */ { MAD_F(0x07843de1) /* 0.469785575 */, 18 }, + /* 6575 */ { MAD_F(0x0784a1ca) /* 0.469880859 */, 18 }, + + /* 6576 */ { MAD_F(0x078505b5) /* 0.469976148 */, 18 }, + /* 6577 */ { MAD_F(0x078569a2) /* 0.470071442 */, 18 }, + /* 6578 */ { MAD_F(0x0785cd8f) /* 0.470166740 */, 18 }, + /* 6579 */ { MAD_F(0x0786317e) /* 0.470262043 */, 18 }, + /* 6580 */ { MAD_F(0x0786956e) /* 0.470357351 */, 18 }, + /* 6581 */ { MAD_F(0x0786f95f) /* 0.470452664 */, 18 }, + /* 6582 */ { MAD_F(0x07875d52) /* 0.470547982 */, 18 }, + /* 6583 */ { MAD_F(0x0787c146) /* 0.470643305 */, 18 }, + /* 6584 */ { MAD_F(0x0788253b) /* 0.470738632 */, 18 }, + /* 6585 */ { MAD_F(0x07888932) /* 0.470833964 */, 18 }, + /* 6586 */ { MAD_F(0x0788ed2a) /* 0.470929301 */, 18 }, + /* 6587 */ { MAD_F(0x07895123) /* 0.471024643 */, 18 }, + /* 6588 */ { MAD_F(0x0789b51d) /* 0.471119990 */, 18 }, + /* 6589 */ { MAD_F(0x078a1919) /* 0.471215341 */, 18 }, + /* 6590 */ { MAD_F(0x078a7d16) /* 0.471310698 */, 18 }, + /* 6591 */ { MAD_F(0x078ae114) /* 0.471406059 */, 18 }, + + /* 6592 */ { MAD_F(0x078b4514) /* 0.471501425 */, 18 }, + /* 6593 */ { MAD_F(0x078ba915) /* 0.471596796 */, 18 }, + /* 6594 */ { MAD_F(0x078c0d17) /* 0.471692171 */, 18 }, + /* 6595 */ { MAD_F(0x078c711a) /* 0.471787552 */, 18 }, + /* 6596 */ { MAD_F(0x078cd51f) /* 0.471882937 */, 18 }, + /* 6597 */ { MAD_F(0x078d3925) /* 0.471978327 */, 18 }, + /* 6598 */ { MAD_F(0x078d9d2d) /* 0.472073722 */, 18 }, + /* 6599 */ { MAD_F(0x078e0135) /* 0.472169122 */, 18 }, + /* 6600 */ { MAD_F(0x078e653f) /* 0.472264527 */, 18 }, + /* 6601 */ { MAD_F(0x078ec94b) /* 0.472359936 */, 18 }, + /* 6602 */ { MAD_F(0x078f2d57) /* 0.472455350 */, 18 }, + /* 6603 */ { MAD_F(0x078f9165) /* 0.472550769 */, 18 }, + /* 6604 */ { MAD_F(0x078ff574) /* 0.472646193 */, 18 }, + /* 6605 */ { MAD_F(0x07905985) /* 0.472741622 */, 18 }, + /* 6606 */ { MAD_F(0x0790bd96) /* 0.472837055 */, 18 }, + /* 6607 */ { MAD_F(0x079121a9) /* 0.472932493 */, 18 }, + + /* 6608 */ { MAD_F(0x079185be) /* 0.473027937 */, 18 }, + /* 6609 */ { MAD_F(0x0791e9d3) /* 0.473123384 */, 18 }, + /* 6610 */ { MAD_F(0x07924dea) /* 0.473218837 */, 18 }, + /* 6611 */ { MAD_F(0x0792b202) /* 0.473314295 */, 18 }, + /* 6612 */ { MAD_F(0x0793161c) /* 0.473409757 */, 18 }, + /* 6613 */ { MAD_F(0x07937a37) /* 0.473505224 */, 18 }, + /* 6614 */ { MAD_F(0x0793de53) /* 0.473600696 */, 18 }, + /* 6615 */ { MAD_F(0x07944270) /* 0.473696173 */, 18 }, + /* 6616 */ { MAD_F(0x0794a68f) /* 0.473791655 */, 18 }, + /* 6617 */ { MAD_F(0x07950aaf) /* 0.473887141 */, 18 }, + /* 6618 */ { MAD_F(0x07956ed0) /* 0.473982632 */, 18 }, + /* 6619 */ { MAD_F(0x0795d2f2) /* 0.474078128 */, 18 }, + /* 6620 */ { MAD_F(0x07963716) /* 0.474173629 */, 18 }, + /* 6621 */ { MAD_F(0x07969b3b) /* 0.474269135 */, 18 }, + /* 6622 */ { MAD_F(0x0796ff62) /* 0.474364645 */, 18 }, + /* 6623 */ { MAD_F(0x07976389) /* 0.474460161 */, 18 }, + + /* 6624 */ { MAD_F(0x0797c7b2) /* 0.474555681 */, 18 }, + /* 6625 */ { MAD_F(0x07982bdd) /* 0.474651205 */, 18 }, + /* 6626 */ { MAD_F(0x07989008) /* 0.474746735 */, 18 }, + /* 6627 */ { MAD_F(0x0798f435) /* 0.474842270 */, 18 }, + /* 6628 */ { MAD_F(0x07995863) /* 0.474937809 */, 18 }, + /* 6629 */ { MAD_F(0x0799bc92) /* 0.475033353 */, 18 }, + /* 6630 */ { MAD_F(0x079a20c3) /* 0.475128902 */, 18 }, + /* 6631 */ { MAD_F(0x079a84f5) /* 0.475224456 */, 18 }, + /* 6632 */ { MAD_F(0x079ae929) /* 0.475320014 */, 18 }, + /* 6633 */ { MAD_F(0x079b4d5d) /* 0.475415578 */, 18 }, + /* 6634 */ { MAD_F(0x079bb193) /* 0.475511146 */, 18 }, + /* 6635 */ { MAD_F(0x079c15ca) /* 0.475606719 */, 18 }, + /* 6636 */ { MAD_F(0x079c7a03) /* 0.475702296 */, 18 }, + /* 6637 */ { MAD_F(0x079cde3c) /* 0.475797879 */, 18 }, + /* 6638 */ { MAD_F(0x079d4277) /* 0.475893466 */, 18 }, + /* 6639 */ { MAD_F(0x079da6b4) /* 0.475989058 */, 18 }, + + /* 6640 */ { MAD_F(0x079e0af1) /* 0.476084655 */, 18 }, + /* 6641 */ { MAD_F(0x079e6f30) /* 0.476180257 */, 18 }, + /* 6642 */ { MAD_F(0x079ed370) /* 0.476275863 */, 18 }, + /* 6643 */ { MAD_F(0x079f37b2) /* 0.476371475 */, 18 }, + /* 6644 */ { MAD_F(0x079f9bf5) /* 0.476467091 */, 18 }, + /* 6645 */ { MAD_F(0x07a00039) /* 0.476562712 */, 18 }, + /* 6646 */ { MAD_F(0x07a0647e) /* 0.476658338 */, 18 }, + /* 6647 */ { MAD_F(0x07a0c8c5) /* 0.476753968 */, 18 }, + /* 6648 */ { MAD_F(0x07a12d0c) /* 0.476849603 */, 18 }, + /* 6649 */ { MAD_F(0x07a19156) /* 0.476945243 */, 18 }, + /* 6650 */ { MAD_F(0x07a1f5a0) /* 0.477040888 */, 18 }, + /* 6651 */ { MAD_F(0x07a259ec) /* 0.477136538 */, 18 }, + /* 6652 */ { MAD_F(0x07a2be39) /* 0.477232193 */, 18 }, + /* 6653 */ { MAD_F(0x07a32287) /* 0.477327852 */, 18 }, + /* 6654 */ { MAD_F(0x07a386d7) /* 0.477423516 */, 18 }, + /* 6655 */ { MAD_F(0x07a3eb28) /* 0.477519185 */, 18 }, + + /* 6656 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 18 }, + /* 6657 */ { MAD_F(0x07a4b3ce) /* 0.477710537 */, 18 }, + /* 6658 */ { MAD_F(0x07a51822) /* 0.477806220 */, 18 }, + /* 6659 */ { MAD_F(0x07a57c78) /* 0.477901908 */, 18 }, + /* 6660 */ { MAD_F(0x07a5e0d0) /* 0.477997601 */, 18 }, + /* 6661 */ { MAD_F(0x07a64528) /* 0.478093299 */, 18 }, + /* 6662 */ { MAD_F(0x07a6a982) /* 0.478189001 */, 18 }, + /* 6663 */ { MAD_F(0x07a70ddd) /* 0.478284708 */, 18 }, + /* 6664 */ { MAD_F(0x07a7723a) /* 0.478380420 */, 18 }, + /* 6665 */ { MAD_F(0x07a7d698) /* 0.478476137 */, 18 }, + /* 6666 */ { MAD_F(0x07a83af7) /* 0.478571858 */, 18 }, + /* 6667 */ { MAD_F(0x07a89f57) /* 0.478667585 */, 18 }, + /* 6668 */ { MAD_F(0x07a903b9) /* 0.478763316 */, 18 }, + /* 6669 */ { MAD_F(0x07a9681c) /* 0.478859052 */, 18 }, + /* 6670 */ { MAD_F(0x07a9cc80) /* 0.478954793 */, 18 }, + /* 6671 */ { MAD_F(0x07aa30e5) /* 0.479050538 */, 18 }, + + /* 6672 */ { MAD_F(0x07aa954c) /* 0.479146288 */, 18 }, + /* 6673 */ { MAD_F(0x07aaf9b4) /* 0.479242043 */, 18 }, + /* 6674 */ { MAD_F(0x07ab5e1e) /* 0.479337803 */, 18 }, + /* 6675 */ { MAD_F(0x07abc288) /* 0.479433568 */, 18 }, + /* 6676 */ { MAD_F(0x07ac26f4) /* 0.479529337 */, 18 }, + /* 6677 */ { MAD_F(0x07ac8b61) /* 0.479625111 */, 18 }, + /* 6678 */ { MAD_F(0x07acefd0) /* 0.479720890 */, 18 }, + /* 6679 */ { MAD_F(0x07ad543f) /* 0.479816674 */, 18 }, + /* 6680 */ { MAD_F(0x07adb8b0) /* 0.479912463 */, 18 }, + /* 6681 */ { MAD_F(0x07ae1d23) /* 0.480008256 */, 18 }, + /* 6682 */ { MAD_F(0x07ae8196) /* 0.480104054 */, 18 }, + /* 6683 */ { MAD_F(0x07aee60b) /* 0.480199857 */, 18 }, + /* 6684 */ { MAD_F(0x07af4a81) /* 0.480295664 */, 18 }, + /* 6685 */ { MAD_F(0x07afaef9) /* 0.480391477 */, 18 }, + /* 6686 */ { MAD_F(0x07b01372) /* 0.480487294 */, 18 }, + /* 6687 */ { MAD_F(0x07b077ec) /* 0.480583116 */, 18 }, + + /* 6688 */ { MAD_F(0x07b0dc67) /* 0.480678943 */, 18 }, + /* 6689 */ { MAD_F(0x07b140e4) /* 0.480774774 */, 18 }, + /* 6690 */ { MAD_F(0x07b1a561) /* 0.480870611 */, 18 }, + /* 6691 */ { MAD_F(0x07b209e1) /* 0.480966452 */, 18 }, + /* 6692 */ { MAD_F(0x07b26e61) /* 0.481062298 */, 18 }, + /* 6693 */ { MAD_F(0x07b2d2e3) /* 0.481158148 */, 18 }, + /* 6694 */ { MAD_F(0x07b33766) /* 0.481254004 */, 18 }, + /* 6695 */ { MAD_F(0x07b39bea) /* 0.481349864 */, 18 }, + /* 6696 */ { MAD_F(0x07b4006f) /* 0.481445729 */, 18 }, + /* 6697 */ { MAD_F(0x07b464f6) /* 0.481541598 */, 18 }, + /* 6698 */ { MAD_F(0x07b4c97e) /* 0.481637473 */, 18 }, + /* 6699 */ { MAD_F(0x07b52e08) /* 0.481733352 */, 18 }, + /* 6700 */ { MAD_F(0x07b59292) /* 0.481829236 */, 18 }, + /* 6701 */ { MAD_F(0x07b5f71e) /* 0.481925125 */, 18 }, + /* 6702 */ { MAD_F(0x07b65bac) /* 0.482021019 */, 18 }, + /* 6703 */ { MAD_F(0x07b6c03a) /* 0.482116917 */, 18 }, + + /* 6704 */ { MAD_F(0x07b724ca) /* 0.482212820 */, 18 }, + /* 6705 */ { MAD_F(0x07b7895b) /* 0.482308728 */, 18 }, + /* 6706 */ { MAD_F(0x07b7eded) /* 0.482404640 */, 18 }, + /* 6707 */ { MAD_F(0x07b85281) /* 0.482500558 */, 18 }, + /* 6708 */ { MAD_F(0x07b8b716) /* 0.482596480 */, 18 }, + /* 6709 */ { MAD_F(0x07b91bac) /* 0.482692407 */, 18 }, + /* 6710 */ { MAD_F(0x07b98044) /* 0.482788339 */, 18 }, + /* 6711 */ { MAD_F(0x07b9e4dc) /* 0.482884275 */, 18 }, + /* 6712 */ { MAD_F(0x07ba4976) /* 0.482980216 */, 18 }, + /* 6713 */ { MAD_F(0x07baae12) /* 0.483076162 */, 18 }, + /* 6714 */ { MAD_F(0x07bb12ae) /* 0.483172113 */, 18 }, + /* 6715 */ { MAD_F(0x07bb774c) /* 0.483268069 */, 18 }, + /* 6716 */ { MAD_F(0x07bbdbeb) /* 0.483364029 */, 18 }, + /* 6717 */ { MAD_F(0x07bc408c) /* 0.483459994 */, 18 }, + /* 6718 */ { MAD_F(0x07bca52d) /* 0.483555964 */, 18 }, + /* 6719 */ { MAD_F(0x07bd09d0) /* 0.483651939 */, 18 }, + + /* 6720 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 18 }, + /* 6721 */ { MAD_F(0x07bdd31a) /* 0.483843902 */, 18 }, + /* 6722 */ { MAD_F(0x07be37c1) /* 0.483939891 */, 18 }, + /* 6723 */ { MAD_F(0x07be9c69) /* 0.484035885 */, 18 }, + /* 6724 */ { MAD_F(0x07bf0113) /* 0.484131883 */, 18 }, + /* 6725 */ { MAD_F(0x07bf65bd) /* 0.484227886 */, 18 }, + /* 6726 */ { MAD_F(0x07bfca69) /* 0.484323894 */, 18 }, + /* 6727 */ { MAD_F(0x07c02f16) /* 0.484419907 */, 18 }, + /* 6728 */ { MAD_F(0x07c093c5) /* 0.484515924 */, 18 }, + /* 6729 */ { MAD_F(0x07c0f875) /* 0.484611946 */, 18 }, + /* 6730 */ { MAD_F(0x07c15d26) /* 0.484707973 */, 18 }, + /* 6731 */ { MAD_F(0x07c1c1d8) /* 0.484804005 */, 18 }, + /* 6732 */ { MAD_F(0x07c2268b) /* 0.484900041 */, 18 }, + /* 6733 */ { MAD_F(0x07c28b40) /* 0.484996083 */, 18 }, + /* 6734 */ { MAD_F(0x07c2eff6) /* 0.485092128 */, 18 }, + /* 6735 */ { MAD_F(0x07c354ae) /* 0.485188179 */, 18 }, + + /* 6736 */ { MAD_F(0x07c3b967) /* 0.485284235 */, 18 }, + /* 6737 */ { MAD_F(0x07c41e21) /* 0.485380295 */, 18 }, + /* 6738 */ { MAD_F(0x07c482dc) /* 0.485476360 */, 18 }, + /* 6739 */ { MAD_F(0x07c4e798) /* 0.485572430 */, 18 }, + /* 6740 */ { MAD_F(0x07c54c56) /* 0.485668504 */, 18 }, + /* 6741 */ { MAD_F(0x07c5b115) /* 0.485764583 */, 18 }, + /* 6742 */ { MAD_F(0x07c615d6) /* 0.485860667 */, 18 }, + /* 6743 */ { MAD_F(0x07c67a97) /* 0.485956756 */, 18 }, + /* 6744 */ { MAD_F(0x07c6df5a) /* 0.486052849 */, 18 }, + /* 6745 */ { MAD_F(0x07c7441e) /* 0.486148948 */, 18 }, + /* 6746 */ { MAD_F(0x07c7a8e4) /* 0.486245051 */, 18 }, + /* 6747 */ { MAD_F(0x07c80daa) /* 0.486341158 */, 18 }, + /* 6748 */ { MAD_F(0x07c87272) /* 0.486437271 */, 18 }, + /* 6749 */ { MAD_F(0x07c8d73c) /* 0.486533388 */, 18 }, + /* 6750 */ { MAD_F(0x07c93c06) /* 0.486629510 */, 18 }, + /* 6751 */ { MAD_F(0x07c9a0d2) /* 0.486725637 */, 18 }, + + /* 6752 */ { MAD_F(0x07ca059f) /* 0.486821768 */, 18 }, + /* 6753 */ { MAD_F(0x07ca6a6d) /* 0.486917905 */, 18 }, + /* 6754 */ { MAD_F(0x07cacf3d) /* 0.487014045 */, 18 }, + /* 6755 */ { MAD_F(0x07cb340e) /* 0.487110191 */, 18 }, + /* 6756 */ { MAD_F(0x07cb98e0) /* 0.487206342 */, 18 }, + /* 6757 */ { MAD_F(0x07cbfdb4) /* 0.487302497 */, 18 }, + /* 6758 */ { MAD_F(0x07cc6288) /* 0.487398657 */, 18 }, + /* 6759 */ { MAD_F(0x07ccc75e) /* 0.487494821 */, 18 }, + /* 6760 */ { MAD_F(0x07cd2c36) /* 0.487590991 */, 18 }, + /* 6761 */ { MAD_F(0x07cd910e) /* 0.487687165 */, 18 }, + /* 6762 */ { MAD_F(0x07cdf5e8) /* 0.487783344 */, 18 }, + /* 6763 */ { MAD_F(0x07ce5ac3) /* 0.487879528 */, 18 }, + /* 6764 */ { MAD_F(0x07cebfa0) /* 0.487975716 */, 18 }, + /* 6765 */ { MAD_F(0x07cf247d) /* 0.488071909 */, 18 }, + /* 6766 */ { MAD_F(0x07cf895c) /* 0.488168107 */, 18 }, + /* 6767 */ { MAD_F(0x07cfee3c) /* 0.488264310 */, 18 }, + + /* 6768 */ { MAD_F(0x07d0531e) /* 0.488360517 */, 18 }, + /* 6769 */ { MAD_F(0x07d0b801) /* 0.488456729 */, 18 }, + /* 6770 */ { MAD_F(0x07d11ce5) /* 0.488552946 */, 18 }, + /* 6771 */ { MAD_F(0x07d181ca) /* 0.488649167 */, 18 }, + /* 6772 */ { MAD_F(0x07d1e6b0) /* 0.488745394 */, 18 }, + /* 6773 */ { MAD_F(0x07d24b98) /* 0.488841625 */, 18 }, + /* 6774 */ { MAD_F(0x07d2b081) /* 0.488937860 */, 18 }, + /* 6775 */ { MAD_F(0x07d3156c) /* 0.489034101 */, 18 }, + /* 6776 */ { MAD_F(0x07d37a57) /* 0.489130346 */, 18 }, + /* 6777 */ { MAD_F(0x07d3df44) /* 0.489226596 */, 18 }, + /* 6778 */ { MAD_F(0x07d44432) /* 0.489322851 */, 18 }, + /* 6779 */ { MAD_F(0x07d4a922) /* 0.489419110 */, 18 }, + /* 6780 */ { MAD_F(0x07d50e13) /* 0.489515375 */, 18 }, + /* 6781 */ { MAD_F(0x07d57305) /* 0.489611643 */, 18 }, + /* 6782 */ { MAD_F(0x07d5d7f8) /* 0.489707917 */, 18 }, + /* 6783 */ { MAD_F(0x07d63cec) /* 0.489804195 */, 18 }, + + /* 6784 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 18 }, + /* 6785 */ { MAD_F(0x07d706d9) /* 0.489996766 */, 18 }, + /* 6786 */ { MAD_F(0x07d76bd2) /* 0.490093059 */, 18 }, + /* 6787 */ { MAD_F(0x07d7d0cb) /* 0.490189356 */, 18 }, + /* 6788 */ { MAD_F(0x07d835c6) /* 0.490285658 */, 18 }, + /* 6789 */ { MAD_F(0x07d89ac2) /* 0.490381965 */, 18 }, + /* 6790 */ { MAD_F(0x07d8ffc0) /* 0.490478277 */, 18 }, + /* 6791 */ { MAD_F(0x07d964be) /* 0.490574593 */, 18 }, + /* 6792 */ { MAD_F(0x07d9c9be) /* 0.490670914 */, 18 }, + /* 6793 */ { MAD_F(0x07da2ebf) /* 0.490767239 */, 18 }, + /* 6794 */ { MAD_F(0x07da93c2) /* 0.490863570 */, 18 }, + /* 6795 */ { MAD_F(0x07daf8c6) /* 0.490959905 */, 18 }, + /* 6796 */ { MAD_F(0x07db5dcb) /* 0.491056245 */, 18 }, + /* 6797 */ { MAD_F(0x07dbc2d1) /* 0.491152589 */, 18 }, + /* 6798 */ { MAD_F(0x07dc27d9) /* 0.491248939 */, 18 }, + /* 6799 */ { MAD_F(0x07dc8ce1) /* 0.491345293 */, 18 }, + + /* 6800 */ { MAD_F(0x07dcf1ec) /* 0.491441651 */, 18 }, + /* 6801 */ { MAD_F(0x07dd56f7) /* 0.491538015 */, 18 }, + /* 6802 */ { MAD_F(0x07ddbc04) /* 0.491634383 */, 18 }, + /* 6803 */ { MAD_F(0x07de2111) /* 0.491730756 */, 18 }, + /* 6804 */ { MAD_F(0x07de8621) /* 0.491827134 */, 18 }, + /* 6805 */ { MAD_F(0x07deeb31) /* 0.491923516 */, 18 }, + /* 6806 */ { MAD_F(0x07df5043) /* 0.492019903 */, 18 }, + /* 6807 */ { MAD_F(0x07dfb556) /* 0.492116295 */, 18 }, + /* 6808 */ { MAD_F(0x07e01a6a) /* 0.492212691 */, 18 }, + /* 6809 */ { MAD_F(0x07e07f80) /* 0.492309093 */, 18 }, + /* 6810 */ { MAD_F(0x07e0e496) /* 0.492405499 */, 18 }, + /* 6811 */ { MAD_F(0x07e149ae) /* 0.492501909 */, 18 }, + /* 6812 */ { MAD_F(0x07e1aec8) /* 0.492598325 */, 18 }, + /* 6813 */ { MAD_F(0x07e213e2) /* 0.492694745 */, 18 }, + /* 6814 */ { MAD_F(0x07e278fe) /* 0.492791170 */, 18 }, + /* 6815 */ { MAD_F(0x07e2de1b) /* 0.492887599 */, 18 }, + + /* 6816 */ { MAD_F(0x07e3433a) /* 0.492984033 */, 18 }, + /* 6817 */ { MAD_F(0x07e3a859) /* 0.493080472 */, 18 }, + /* 6818 */ { MAD_F(0x07e40d7a) /* 0.493176916 */, 18 }, + /* 6819 */ { MAD_F(0x07e4729c) /* 0.493273365 */, 18 }, + /* 6820 */ { MAD_F(0x07e4d7c0) /* 0.493369818 */, 18 }, + /* 6821 */ { MAD_F(0x07e53ce4) /* 0.493466275 */, 18 }, + /* 6822 */ { MAD_F(0x07e5a20a) /* 0.493562738 */, 18 }, + /* 6823 */ { MAD_F(0x07e60732) /* 0.493659205 */, 18 }, + /* 6824 */ { MAD_F(0x07e66c5a) /* 0.493755677 */, 18 }, + /* 6825 */ { MAD_F(0x07e6d184) /* 0.493852154 */, 18 }, + /* 6826 */ { MAD_F(0x07e736af) /* 0.493948635 */, 18 }, + /* 6827 */ { MAD_F(0x07e79bdb) /* 0.494045122 */, 18 }, + /* 6828 */ { MAD_F(0x07e80109) /* 0.494141612 */, 18 }, + /* 6829 */ { MAD_F(0x07e86638) /* 0.494238108 */, 18 }, + /* 6830 */ { MAD_F(0x07e8cb68) /* 0.494334608 */, 18 }, + /* 6831 */ { MAD_F(0x07e93099) /* 0.494431113 */, 18 }, + + /* 6832 */ { MAD_F(0x07e995cc) /* 0.494527623 */, 18 }, + /* 6833 */ { MAD_F(0x07e9fb00) /* 0.494624137 */, 18 }, + /* 6834 */ { MAD_F(0x07ea6035) /* 0.494720656 */, 18 }, + /* 6835 */ { MAD_F(0x07eac56b) /* 0.494817180 */, 18 }, + /* 6836 */ { MAD_F(0x07eb2aa3) /* 0.494913709 */, 18 }, + /* 6837 */ { MAD_F(0x07eb8fdc) /* 0.495010242 */, 18 }, + /* 6838 */ { MAD_F(0x07ebf516) /* 0.495106780 */, 18 }, + /* 6839 */ { MAD_F(0x07ec5a51) /* 0.495203322 */, 18 }, + /* 6840 */ { MAD_F(0x07ecbf8e) /* 0.495299870 */, 18 }, + /* 6841 */ { MAD_F(0x07ed24cc) /* 0.495396422 */, 18 }, + /* 6842 */ { MAD_F(0x07ed8a0b) /* 0.495492978 */, 18 }, + /* 6843 */ { MAD_F(0x07edef4c) /* 0.495589540 */, 18 }, + /* 6844 */ { MAD_F(0x07ee548e) /* 0.495686106 */, 18 }, + /* 6845 */ { MAD_F(0x07eeb9d1) /* 0.495782677 */, 18 }, + /* 6846 */ { MAD_F(0x07ef1f15) /* 0.495879252 */, 18 }, + /* 6847 */ { MAD_F(0x07ef845b) /* 0.495975833 */, 18 }, + + /* 6848 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 18 }, + /* 6849 */ { MAD_F(0x07f04ee9) /* 0.496169007 */, 18 }, + /* 6850 */ { MAD_F(0x07f0b433) /* 0.496265602 */, 18 }, + /* 6851 */ { MAD_F(0x07f1197d) /* 0.496362201 */, 18 }, + /* 6852 */ { MAD_F(0x07f17ec9) /* 0.496458804 */, 18 }, + /* 6853 */ { MAD_F(0x07f1e416) /* 0.496555413 */, 18 }, + /* 6854 */ { MAD_F(0x07f24965) /* 0.496652026 */, 18 }, + /* 6855 */ { MAD_F(0x07f2aeb5) /* 0.496748644 */, 18 }, + /* 6856 */ { MAD_F(0x07f31405) /* 0.496845266 */, 18 }, + /* 6857 */ { MAD_F(0x07f37958) /* 0.496941894 */, 18 }, + /* 6858 */ { MAD_F(0x07f3deab) /* 0.497038526 */, 18 }, + /* 6859 */ { MAD_F(0x07f44400) /* 0.497135162 */, 18 }, + /* 6860 */ { MAD_F(0x07f4a956) /* 0.497231804 */, 18 }, + /* 6861 */ { MAD_F(0x07f50ead) /* 0.497328450 */, 18 }, + /* 6862 */ { MAD_F(0x07f57405) /* 0.497425100 */, 18 }, + /* 6863 */ { MAD_F(0x07f5d95f) /* 0.497521756 */, 18 }, + + /* 6864 */ { MAD_F(0x07f63eba) /* 0.497618416 */, 18 }, + /* 6865 */ { MAD_F(0x07f6a416) /* 0.497715081 */, 18 }, + /* 6866 */ { MAD_F(0x07f70974) /* 0.497811750 */, 18 }, + /* 6867 */ { MAD_F(0x07f76ed3) /* 0.497908425 */, 18 }, + /* 6868 */ { MAD_F(0x07f7d433) /* 0.498005103 */, 18 }, + /* 6869 */ { MAD_F(0x07f83994) /* 0.498101787 */, 18 }, + /* 6870 */ { MAD_F(0x07f89ef7) /* 0.498198475 */, 18 }, + /* 6871 */ { MAD_F(0x07f9045a) /* 0.498295168 */, 18 }, + /* 6872 */ { MAD_F(0x07f969c0) /* 0.498391866 */, 18 }, + /* 6873 */ { MAD_F(0x07f9cf26) /* 0.498488568 */, 18 }, + /* 6874 */ { MAD_F(0x07fa348e) /* 0.498585275 */, 18 }, + /* 6875 */ { MAD_F(0x07fa99f6) /* 0.498681987 */, 18 }, + /* 6876 */ { MAD_F(0x07faff60) /* 0.498778704 */, 18 }, + /* 6877 */ { MAD_F(0x07fb64cc) /* 0.498875425 */, 18 }, + /* 6878 */ { MAD_F(0x07fbca38) /* 0.498972150 */, 18 }, + /* 6879 */ { MAD_F(0x07fc2fa6) /* 0.499068881 */, 18 }, + + /* 6880 */ { MAD_F(0x07fc9516) /* 0.499165616 */, 18 }, + /* 6881 */ { MAD_F(0x07fcfa86) /* 0.499262356 */, 18 }, + /* 6882 */ { MAD_F(0x07fd5ff8) /* 0.499359101 */, 18 }, + /* 6883 */ { MAD_F(0x07fdc56b) /* 0.499455850 */, 18 }, + /* 6884 */ { MAD_F(0x07fe2adf) /* 0.499552604 */, 18 }, + /* 6885 */ { MAD_F(0x07fe9054) /* 0.499649362 */, 18 }, + /* 6886 */ { MAD_F(0x07fef5cb) /* 0.499746126 */, 18 }, + /* 6887 */ { MAD_F(0x07ff5b43) /* 0.499842894 */, 18 }, + /* 6888 */ { MAD_F(0x07ffc0bc) /* 0.499939666 */, 18 }, + /* 6889 */ { MAD_F(0x0400131b) /* 0.250018222 */, 19 }, + /* 6890 */ { MAD_F(0x040045d9) /* 0.250066613 */, 19 }, + /* 6891 */ { MAD_F(0x04007897) /* 0.250115006 */, 19 }, + /* 6892 */ { MAD_F(0x0400ab57) /* 0.250163402 */, 19 }, + /* 6893 */ { MAD_F(0x0400de16) /* 0.250211800 */, 19 }, + /* 6894 */ { MAD_F(0x040110d7) /* 0.250260200 */, 19 }, + /* 6895 */ { MAD_F(0x04014398) /* 0.250308603 */, 19 }, + + /* 6896 */ { MAD_F(0x04017659) /* 0.250357008 */, 19 }, + /* 6897 */ { MAD_F(0x0401a91c) /* 0.250405415 */, 19 }, + /* 6898 */ { MAD_F(0x0401dbdf) /* 0.250453825 */, 19 }, + /* 6899 */ { MAD_F(0x04020ea2) /* 0.250502237 */, 19 }, + /* 6900 */ { MAD_F(0x04024166) /* 0.250550652 */, 19 }, + /* 6901 */ { MAD_F(0x0402742b) /* 0.250599068 */, 19 }, + /* 6902 */ { MAD_F(0x0402a6f0) /* 0.250647488 */, 19 }, + /* 6903 */ { MAD_F(0x0402d9b6) /* 0.250695909 */, 19 }, + /* 6904 */ { MAD_F(0x04030c7d) /* 0.250744333 */, 19 }, + /* 6905 */ { MAD_F(0x04033f44) /* 0.250792759 */, 19 }, + /* 6906 */ { MAD_F(0x0403720c) /* 0.250841187 */, 19 }, + /* 6907 */ { MAD_F(0x0403a4d5) /* 0.250889618 */, 19 }, + /* 6908 */ { MAD_F(0x0403d79e) /* 0.250938051 */, 19 }, + /* 6909 */ { MAD_F(0x04040a68) /* 0.250986487 */, 19 }, + /* 6910 */ { MAD_F(0x04043d32) /* 0.251034924 */, 19 }, + /* 6911 */ { MAD_F(0x04046ffd) /* 0.251083365 */, 19 }, + + /* 6912 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 19 }, + /* 6913 */ { MAD_F(0x0404d595) /* 0.251180252 */, 19 }, + /* 6914 */ { MAD_F(0x04050862) /* 0.251228699 */, 19 }, + /* 6915 */ { MAD_F(0x04053b30) /* 0.251277148 */, 19 }, + /* 6916 */ { MAD_F(0x04056dfe) /* 0.251325600 */, 19 }, + /* 6917 */ { MAD_F(0x0405a0cd) /* 0.251374054 */, 19 }, + /* 6918 */ { MAD_F(0x0405d39c) /* 0.251422511 */, 19 }, + /* 6919 */ { MAD_F(0x0406066c) /* 0.251470970 */, 19 }, + /* 6920 */ { MAD_F(0x0406393d) /* 0.251519431 */, 19 }, + /* 6921 */ { MAD_F(0x04066c0e) /* 0.251567894 */, 19 }, + /* 6922 */ { MAD_F(0x04069ee0) /* 0.251616360 */, 19 }, + /* 6923 */ { MAD_F(0x0406d1b3) /* 0.251664828 */, 19 }, + /* 6924 */ { MAD_F(0x04070486) /* 0.251713299 */, 19 }, + /* 6925 */ { MAD_F(0x0407375a) /* 0.251761772 */, 19 }, + /* 6926 */ { MAD_F(0x04076a2e) /* 0.251810247 */, 19 }, + /* 6927 */ { MAD_F(0x04079d03) /* 0.251858724 */, 19 }, + + /* 6928 */ { MAD_F(0x0407cfd9) /* 0.251907204 */, 19 }, + /* 6929 */ { MAD_F(0x040802af) /* 0.251955686 */, 19 }, + /* 6930 */ { MAD_F(0x04083586) /* 0.252004171 */, 19 }, + /* 6931 */ { MAD_F(0x0408685e) /* 0.252052658 */, 19 }, + /* 6932 */ { MAD_F(0x04089b36) /* 0.252101147 */, 19 }, + /* 6933 */ { MAD_F(0x0408ce0f) /* 0.252149638 */, 19 }, + /* 6934 */ { MAD_F(0x040900e8) /* 0.252198132 */, 19 }, + /* 6935 */ { MAD_F(0x040933c2) /* 0.252246628 */, 19 }, + /* 6936 */ { MAD_F(0x0409669d) /* 0.252295127 */, 19 }, + /* 6937 */ { MAD_F(0x04099978) /* 0.252343627 */, 19 }, + /* 6938 */ { MAD_F(0x0409cc54) /* 0.252392131 */, 19 }, + /* 6939 */ { MAD_F(0x0409ff31) /* 0.252440636 */, 19 }, + /* 6940 */ { MAD_F(0x040a320e) /* 0.252489144 */, 19 }, + /* 6941 */ { MAD_F(0x040a64ec) /* 0.252537654 */, 19 }, + /* 6942 */ { MAD_F(0x040a97cb) /* 0.252586166 */, 19 }, + /* 6943 */ { MAD_F(0x040acaaa) /* 0.252634681 */, 19 }, + + /* 6944 */ { MAD_F(0x040afd89) /* 0.252683198 */, 19 }, + /* 6945 */ { MAD_F(0x040b306a) /* 0.252731718 */, 19 }, + /* 6946 */ { MAD_F(0x040b634b) /* 0.252780240 */, 19 }, + /* 6947 */ { MAD_F(0x040b962c) /* 0.252828764 */, 19 }, + /* 6948 */ { MAD_F(0x040bc90e) /* 0.252877290 */, 19 }, + /* 6949 */ { MAD_F(0x040bfbf1) /* 0.252925819 */, 19 }, + /* 6950 */ { MAD_F(0x040c2ed5) /* 0.252974350 */, 19 }, + /* 6951 */ { MAD_F(0x040c61b9) /* 0.253022883 */, 19 }, + /* 6952 */ { MAD_F(0x040c949e) /* 0.253071419 */, 19 }, + /* 6953 */ { MAD_F(0x040cc783) /* 0.253119957 */, 19 }, + /* 6954 */ { MAD_F(0x040cfa69) /* 0.253168498 */, 19 }, + /* 6955 */ { MAD_F(0x040d2d4f) /* 0.253217040 */, 19 }, + /* 6956 */ { MAD_F(0x040d6037) /* 0.253265585 */, 19 }, + /* 6957 */ { MAD_F(0x040d931e) /* 0.253314133 */, 19 }, + /* 6958 */ { MAD_F(0x040dc607) /* 0.253362682 */, 19 }, + /* 6959 */ { MAD_F(0x040df8f0) /* 0.253411234 */, 19 }, + + /* 6960 */ { MAD_F(0x040e2bda) /* 0.253459789 */, 19 }, + /* 6961 */ { MAD_F(0x040e5ec4) /* 0.253508345 */, 19 }, + /* 6962 */ { MAD_F(0x040e91af) /* 0.253556904 */, 19 }, + /* 6963 */ { MAD_F(0x040ec49b) /* 0.253605466 */, 19 }, + /* 6964 */ { MAD_F(0x040ef787) /* 0.253654029 */, 19 }, + /* 6965 */ { MAD_F(0x040f2a74) /* 0.253702595 */, 19 }, + /* 6966 */ { MAD_F(0x040f5d61) /* 0.253751164 */, 19 }, + /* 6967 */ { MAD_F(0x040f904f) /* 0.253799734 */, 19 }, + /* 6968 */ { MAD_F(0x040fc33e) /* 0.253848307 */, 19 }, + /* 6969 */ { MAD_F(0x040ff62d) /* 0.253896883 */, 19 }, + /* 6970 */ { MAD_F(0x0410291d) /* 0.253945460 */, 19 }, + /* 6971 */ { MAD_F(0x04105c0e) /* 0.253994040 */, 19 }, + /* 6972 */ { MAD_F(0x04108eff) /* 0.254042622 */, 19 }, + /* 6973 */ { MAD_F(0x0410c1f1) /* 0.254091207 */, 19 }, + /* 6974 */ { MAD_F(0x0410f4e3) /* 0.254139794 */, 19 }, + /* 6975 */ { MAD_F(0x041127d6) /* 0.254188383 */, 19 }, + + /* 6976 */ { MAD_F(0x04115aca) /* 0.254236974 */, 19 }, + /* 6977 */ { MAD_F(0x04118dbe) /* 0.254285568 */, 19 }, + /* 6978 */ { MAD_F(0x0411c0b3) /* 0.254334165 */, 19 }, + /* 6979 */ { MAD_F(0x0411f3a9) /* 0.254382763 */, 19 }, + /* 6980 */ { MAD_F(0x0412269f) /* 0.254431364 */, 19 }, + /* 6981 */ { MAD_F(0x04125996) /* 0.254479967 */, 19 }, + /* 6982 */ { MAD_F(0x04128c8d) /* 0.254528572 */, 19 }, + /* 6983 */ { MAD_F(0x0412bf85) /* 0.254577180 */, 19 }, + /* 6984 */ { MAD_F(0x0412f27e) /* 0.254625790 */, 19 }, + /* 6985 */ { MAD_F(0x04132577) /* 0.254674403 */, 19 }, + /* 6986 */ { MAD_F(0x04135871) /* 0.254723017 */, 19 }, + /* 6987 */ { MAD_F(0x04138b6c) /* 0.254771635 */, 19 }, + /* 6988 */ { MAD_F(0x0413be67) /* 0.254820254 */, 19 }, + /* 6989 */ { MAD_F(0x0413f163) /* 0.254868876 */, 19 }, + /* 6990 */ { MAD_F(0x0414245f) /* 0.254917500 */, 19 }, + /* 6991 */ { MAD_F(0x0414575c) /* 0.254966126 */, 19 }, + + /* 6992 */ { MAD_F(0x04148a5a) /* 0.255014755 */, 19 }, + /* 6993 */ { MAD_F(0x0414bd58) /* 0.255063386 */, 19 }, + /* 6994 */ { MAD_F(0x0414f057) /* 0.255112019 */, 19 }, + /* 6995 */ { MAD_F(0x04152356) /* 0.255160655 */, 19 }, + /* 6996 */ { MAD_F(0x04155657) /* 0.255209292 */, 19 }, + /* 6997 */ { MAD_F(0x04158957) /* 0.255257933 */, 19 }, + /* 6998 */ { MAD_F(0x0415bc59) /* 0.255306575 */, 19 }, + /* 6999 */ { MAD_F(0x0415ef5b) /* 0.255355220 */, 19 }, + /* 7000 */ { MAD_F(0x0416225d) /* 0.255403867 */, 19 }, + /* 7001 */ { MAD_F(0x04165561) /* 0.255452517 */, 19 }, + /* 7002 */ { MAD_F(0x04168864) /* 0.255501169 */, 19 }, + /* 7003 */ { MAD_F(0x0416bb69) /* 0.255549823 */, 19 }, + /* 7004 */ { MAD_F(0x0416ee6e) /* 0.255598479 */, 19 }, + /* 7005 */ { MAD_F(0x04172174) /* 0.255647138 */, 19 }, + /* 7006 */ { MAD_F(0x0417547a) /* 0.255695799 */, 19 }, + /* 7007 */ { MAD_F(0x04178781) /* 0.255744463 */, 19 }, + + /* 7008 */ { MAD_F(0x0417ba89) /* 0.255793128 */, 19 }, + /* 7009 */ { MAD_F(0x0417ed91) /* 0.255841796 */, 19 }, + /* 7010 */ { MAD_F(0x0418209a) /* 0.255890467 */, 19 }, + /* 7011 */ { MAD_F(0x041853a3) /* 0.255939139 */, 19 }, + /* 7012 */ { MAD_F(0x041886ad) /* 0.255987814 */, 19 }, + /* 7013 */ { MAD_F(0x0418b9b8) /* 0.256036492 */, 19 }, + /* 7014 */ { MAD_F(0x0418ecc3) /* 0.256085171 */, 19 }, + /* 7015 */ { MAD_F(0x04191fcf) /* 0.256133853 */, 19 }, + /* 7016 */ { MAD_F(0x041952dc) /* 0.256182537 */, 19 }, + /* 7017 */ { MAD_F(0x041985e9) /* 0.256231224 */, 19 }, + /* 7018 */ { MAD_F(0x0419b8f7) /* 0.256279913 */, 19 }, + /* 7019 */ { MAD_F(0x0419ec05) /* 0.256328604 */, 19 }, + /* 7020 */ { MAD_F(0x041a1f15) /* 0.256377297 */, 19 }, + /* 7021 */ { MAD_F(0x041a5224) /* 0.256425993 */, 19 }, + /* 7022 */ { MAD_F(0x041a8534) /* 0.256474691 */, 19 }, + /* 7023 */ { MAD_F(0x041ab845) /* 0.256523392 */, 19 }, + + /* 7024 */ { MAD_F(0x041aeb57) /* 0.256572095 */, 19 }, + /* 7025 */ { MAD_F(0x041b1e69) /* 0.256620800 */, 19 }, + /* 7026 */ { MAD_F(0x041b517c) /* 0.256669507 */, 19 }, + /* 7027 */ { MAD_F(0x041b848f) /* 0.256718217 */, 19 }, + /* 7028 */ { MAD_F(0x041bb7a3) /* 0.256766929 */, 19 }, + /* 7029 */ { MAD_F(0x041beab8) /* 0.256815643 */, 19 }, + /* 7030 */ { MAD_F(0x041c1dcd) /* 0.256864359 */, 19 }, + /* 7031 */ { MAD_F(0x041c50e3) /* 0.256913078 */, 19 }, + /* 7032 */ { MAD_F(0x041c83fa) /* 0.256961800 */, 19 }, + /* 7033 */ { MAD_F(0x041cb711) /* 0.257010523 */, 19 }, + /* 7034 */ { MAD_F(0x041cea28) /* 0.257059249 */, 19 }, + /* 7035 */ { MAD_F(0x041d1d41) /* 0.257107977 */, 19 }, + /* 7036 */ { MAD_F(0x041d505a) /* 0.257156708 */, 19 }, + /* 7037 */ { MAD_F(0x041d8373) /* 0.257205440 */, 19 }, + /* 7038 */ { MAD_F(0x041db68e) /* 0.257254175 */, 19 }, + /* 7039 */ { MAD_F(0x041de9a8) /* 0.257302913 */, 19 }, + + /* 7040 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 19 }, + /* 7041 */ { MAD_F(0x041e4fe0) /* 0.257400394 */, 19 }, + /* 7042 */ { MAD_F(0x041e82fd) /* 0.257449139 */, 19 }, + /* 7043 */ { MAD_F(0x041eb61a) /* 0.257497885 */, 19 }, + /* 7044 */ { MAD_F(0x041ee938) /* 0.257546634 */, 19 }, + /* 7045 */ { MAD_F(0x041f1c57) /* 0.257595386 */, 19 }, + /* 7046 */ { MAD_F(0x041f4f76) /* 0.257644139 */, 19 }, + /* 7047 */ { MAD_F(0x041f8296) /* 0.257692895 */, 19 }, + /* 7048 */ { MAD_F(0x041fb5b6) /* 0.257741653 */, 19 }, + /* 7049 */ { MAD_F(0x041fe8d7) /* 0.257790414 */, 19 }, + /* 7050 */ { MAD_F(0x04201bf9) /* 0.257839176 */, 19 }, + /* 7051 */ { MAD_F(0x04204f1b) /* 0.257887941 */, 19 }, + /* 7052 */ { MAD_F(0x0420823e) /* 0.257936709 */, 19 }, + /* 7053 */ { MAD_F(0x0420b561) /* 0.257985478 */, 19 }, + /* 7054 */ { MAD_F(0x0420e885) /* 0.258034250 */, 19 }, + /* 7055 */ { MAD_F(0x04211baa) /* 0.258083025 */, 19 }, + + /* 7056 */ { MAD_F(0x04214ed0) /* 0.258131801 */, 19 }, + /* 7057 */ { MAD_F(0x042181f6) /* 0.258180580 */, 19 }, + /* 7058 */ { MAD_F(0x0421b51c) /* 0.258229361 */, 19 }, + /* 7059 */ { MAD_F(0x0421e843) /* 0.258278145 */, 19 }, + /* 7060 */ { MAD_F(0x04221b6b) /* 0.258326931 */, 19 }, + /* 7061 */ { MAD_F(0x04224e94) /* 0.258375719 */, 19 }, + /* 7062 */ { MAD_F(0x042281bd) /* 0.258424509 */, 19 }, + /* 7063 */ { MAD_F(0x0422b4e6) /* 0.258473302 */, 19 }, + /* 7064 */ { MAD_F(0x0422e811) /* 0.258522097 */, 19 }, + /* 7065 */ { MAD_F(0x04231b3c) /* 0.258570894 */, 19 }, + /* 7066 */ { MAD_F(0x04234e67) /* 0.258619694 */, 19 }, + /* 7067 */ { MAD_F(0x04238193) /* 0.258668496 */, 19 }, + /* 7068 */ { MAD_F(0x0423b4c0) /* 0.258717300 */, 19 }, + /* 7069 */ { MAD_F(0x0423e7ee) /* 0.258766106 */, 19 }, + /* 7070 */ { MAD_F(0x04241b1c) /* 0.258814915 */, 19 }, + /* 7071 */ { MAD_F(0x04244e4a) /* 0.258863726 */, 19 }, + + /* 7072 */ { MAD_F(0x04248179) /* 0.258912540 */, 19 }, + /* 7073 */ { MAD_F(0x0424b4a9) /* 0.258961356 */, 19 }, + /* 7074 */ { MAD_F(0x0424e7da) /* 0.259010174 */, 19 }, + /* 7075 */ { MAD_F(0x04251b0b) /* 0.259058994 */, 19 }, + /* 7076 */ { MAD_F(0x04254e3d) /* 0.259107817 */, 19 }, + /* 7077 */ { MAD_F(0x0425816f) /* 0.259156642 */, 19 }, + /* 7078 */ { MAD_F(0x0425b4a2) /* 0.259205469 */, 19 }, + /* 7079 */ { MAD_F(0x0425e7d6) /* 0.259254298 */, 19 }, + /* 7080 */ { MAD_F(0x04261b0a) /* 0.259303130 */, 19 }, + /* 7081 */ { MAD_F(0x04264e3f) /* 0.259351964 */, 19 }, + /* 7082 */ { MAD_F(0x04268174) /* 0.259400801 */, 19 }, + /* 7083 */ { MAD_F(0x0426b4aa) /* 0.259449639 */, 19 }, + /* 7084 */ { MAD_F(0x0426e7e1) /* 0.259498480 */, 19 }, + /* 7085 */ { MAD_F(0x04271b18) /* 0.259547324 */, 19 }, + /* 7086 */ { MAD_F(0x04274e50) /* 0.259596169 */, 19 }, + /* 7087 */ { MAD_F(0x04278188) /* 0.259645017 */, 19 }, + + /* 7088 */ { MAD_F(0x0427b4c2) /* 0.259693868 */, 19 }, + /* 7089 */ { MAD_F(0x0427e7fb) /* 0.259742720 */, 19 }, + /* 7090 */ { MAD_F(0x04281b36) /* 0.259791575 */, 19 }, + /* 7091 */ { MAD_F(0x04284e71) /* 0.259840432 */, 19 }, + /* 7092 */ { MAD_F(0x042881ac) /* 0.259889291 */, 19 }, + /* 7093 */ { MAD_F(0x0428b4e8) /* 0.259938153 */, 19 }, + /* 7094 */ { MAD_F(0x0428e825) /* 0.259987017 */, 19 }, + /* 7095 */ { MAD_F(0x04291b63) /* 0.260035883 */, 19 }, + /* 7096 */ { MAD_F(0x04294ea1) /* 0.260084752 */, 19 }, + /* 7097 */ { MAD_F(0x042981df) /* 0.260133623 */, 19 }, + /* 7098 */ { MAD_F(0x0429b51f) /* 0.260182496 */, 19 }, + /* 7099 */ { MAD_F(0x0429e85f) /* 0.260231372 */, 19 }, + /* 7100 */ { MAD_F(0x042a1b9f) /* 0.260280249 */, 19 }, + /* 7101 */ { MAD_F(0x042a4ee0) /* 0.260329129 */, 19 }, + /* 7102 */ { MAD_F(0x042a8222) /* 0.260378012 */, 19 }, + /* 7103 */ { MAD_F(0x042ab564) /* 0.260426896 */, 19 }, + + /* 7104 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 19 }, + /* 7105 */ { MAD_F(0x042b1beb) /* 0.260524673 */, 19 }, + /* 7106 */ { MAD_F(0x042b4f2f) /* 0.260573564 */, 19 }, + /* 7107 */ { MAD_F(0x042b8274) /* 0.260622458 */, 19 }, + /* 7108 */ { MAD_F(0x042bb5ba) /* 0.260671354 */, 19 }, + /* 7109 */ { MAD_F(0x042be900) /* 0.260720252 */, 19 }, + /* 7110 */ { MAD_F(0x042c1c46) /* 0.260769153 */, 19 }, + /* 7111 */ { MAD_F(0x042c4f8e) /* 0.260818056 */, 19 }, + /* 7112 */ { MAD_F(0x042c82d6) /* 0.260866961 */, 19 }, + /* 7113 */ { MAD_F(0x042cb61e) /* 0.260915869 */, 19 }, + /* 7114 */ { MAD_F(0x042ce967) /* 0.260964779 */, 19 }, + /* 7115 */ { MAD_F(0x042d1cb1) /* 0.261013691 */, 19 }, + /* 7116 */ { MAD_F(0x042d4ffb) /* 0.261062606 */, 19 }, + /* 7117 */ { MAD_F(0x042d8346) /* 0.261111522 */, 19 }, + /* 7118 */ { MAD_F(0x042db692) /* 0.261160441 */, 19 }, + /* 7119 */ { MAD_F(0x042de9de) /* 0.261209363 */, 19 }, + + /* 7120 */ { MAD_F(0x042e1d2b) /* 0.261258286 */, 19 }, + /* 7121 */ { MAD_F(0x042e5078) /* 0.261307212 */, 19 }, + /* 7122 */ { MAD_F(0x042e83c6) /* 0.261356140 */, 19 }, + /* 7123 */ { MAD_F(0x042eb715) /* 0.261405071 */, 19 }, + /* 7124 */ { MAD_F(0x042eea64) /* 0.261454004 */, 19 }, + /* 7125 */ { MAD_F(0x042f1db4) /* 0.261502939 */, 19 }, + /* 7126 */ { MAD_F(0x042f5105) /* 0.261551876 */, 19 }, + /* 7127 */ { MAD_F(0x042f8456) /* 0.261600816 */, 19 }, + /* 7128 */ { MAD_F(0x042fb7a8) /* 0.261649758 */, 19 }, + /* 7129 */ { MAD_F(0x042feafa) /* 0.261698702 */, 19 }, + /* 7130 */ { MAD_F(0x04301e4d) /* 0.261747649 */, 19 }, + /* 7131 */ { MAD_F(0x043051a1) /* 0.261796597 */, 19 }, + /* 7132 */ { MAD_F(0x043084f5) /* 0.261845548 */, 19 }, + /* 7133 */ { MAD_F(0x0430b84a) /* 0.261894502 */, 19 }, + /* 7134 */ { MAD_F(0x0430eb9f) /* 0.261943458 */, 19 }, + /* 7135 */ { MAD_F(0x04311ef5) /* 0.261992416 */, 19 }, + + /* 7136 */ { MAD_F(0x0431524c) /* 0.262041376 */, 19 }, + /* 7137 */ { MAD_F(0x043185a3) /* 0.262090338 */, 19 }, + /* 7138 */ { MAD_F(0x0431b8fb) /* 0.262139303 */, 19 }, + /* 7139 */ { MAD_F(0x0431ec54) /* 0.262188270 */, 19 }, + /* 7140 */ { MAD_F(0x04321fad) /* 0.262237240 */, 19 }, + /* 7141 */ { MAD_F(0x04325306) /* 0.262286211 */, 19 }, + /* 7142 */ { MAD_F(0x04328661) /* 0.262335185 */, 19 }, + /* 7143 */ { MAD_F(0x0432b9bc) /* 0.262384162 */, 19 }, + /* 7144 */ { MAD_F(0x0432ed17) /* 0.262433140 */, 19 }, + /* 7145 */ { MAD_F(0x04332074) /* 0.262482121 */, 19 }, + /* 7146 */ { MAD_F(0x043353d0) /* 0.262531104 */, 19 }, + /* 7147 */ { MAD_F(0x0433872e) /* 0.262580089 */, 19 }, + /* 7148 */ { MAD_F(0x0433ba8c) /* 0.262629077 */, 19 }, + /* 7149 */ { MAD_F(0x0433edea) /* 0.262678067 */, 19 }, + /* 7150 */ { MAD_F(0x0434214a) /* 0.262727059 */, 19 }, + /* 7151 */ { MAD_F(0x043454aa) /* 0.262776054 */, 19 }, + + /* 7152 */ { MAD_F(0x0434880a) /* 0.262825051 */, 19 }, + /* 7153 */ { MAD_F(0x0434bb6b) /* 0.262874050 */, 19 }, + /* 7154 */ { MAD_F(0x0434eecd) /* 0.262923051 */, 19 }, + /* 7155 */ { MAD_F(0x0435222f) /* 0.262972055 */, 19 }, + /* 7156 */ { MAD_F(0x04355592) /* 0.263021061 */, 19 }, + /* 7157 */ { MAD_F(0x043588f6) /* 0.263070069 */, 19 }, + /* 7158 */ { MAD_F(0x0435bc5a) /* 0.263119079 */, 19 }, + /* 7159 */ { MAD_F(0x0435efbf) /* 0.263168092 */, 19 }, + /* 7160 */ { MAD_F(0x04362324) /* 0.263217107 */, 19 }, + /* 7161 */ { MAD_F(0x0436568a) /* 0.263266125 */, 19 }, + /* 7162 */ { MAD_F(0x043689f1) /* 0.263315144 */, 19 }, + /* 7163 */ { MAD_F(0x0436bd58) /* 0.263364166 */, 19 }, + /* 7164 */ { MAD_F(0x0436f0c0) /* 0.263413191 */, 19 }, + /* 7165 */ { MAD_F(0x04372428) /* 0.263462217 */, 19 }, + /* 7166 */ { MAD_F(0x04375791) /* 0.263511246 */, 19 }, + /* 7167 */ { MAD_F(0x04378afb) /* 0.263560277 */, 19 }, + + /* 7168 */ { MAD_F(0x0437be65) /* 0.263609310 */, 19 }, + /* 7169 */ { MAD_F(0x0437f1d0) /* 0.263658346 */, 19 }, + /* 7170 */ { MAD_F(0x0438253c) /* 0.263707384 */, 19 }, + /* 7171 */ { MAD_F(0x043858a8) /* 0.263756424 */, 19 }, + /* 7172 */ { MAD_F(0x04388c14) /* 0.263805466 */, 19 }, + /* 7173 */ { MAD_F(0x0438bf82) /* 0.263854511 */, 19 }, + /* 7174 */ { MAD_F(0x0438f2f0) /* 0.263903558 */, 19 }, + /* 7175 */ { MAD_F(0x0439265e) /* 0.263952607 */, 19 }, + /* 7176 */ { MAD_F(0x043959cd) /* 0.264001659 */, 19 }, + /* 7177 */ { MAD_F(0x04398d3d) /* 0.264050713 */, 19 }, + /* 7178 */ { MAD_F(0x0439c0ae) /* 0.264099769 */, 19 }, + /* 7179 */ { MAD_F(0x0439f41f) /* 0.264148827 */, 19 }, + /* 7180 */ { MAD_F(0x043a2790) /* 0.264197888 */, 19 }, + /* 7181 */ { MAD_F(0x043a5b02) /* 0.264246951 */, 19 }, + /* 7182 */ { MAD_F(0x043a8e75) /* 0.264296016 */, 19 }, + /* 7183 */ { MAD_F(0x043ac1e9) /* 0.264345084 */, 19 }, + + /* 7184 */ { MAD_F(0x043af55d) /* 0.264394153 */, 19 }, + /* 7185 */ { MAD_F(0x043b28d2) /* 0.264443225 */, 19 }, + /* 7186 */ { MAD_F(0x043b5c47) /* 0.264492300 */, 19 }, + /* 7187 */ { MAD_F(0x043b8fbd) /* 0.264541376 */, 19 }, + /* 7188 */ { MAD_F(0x043bc333) /* 0.264590455 */, 19 }, + /* 7189 */ { MAD_F(0x043bf6aa) /* 0.264639536 */, 19 }, + /* 7190 */ { MAD_F(0x043c2a22) /* 0.264688620 */, 19 }, + /* 7191 */ { MAD_F(0x043c5d9a) /* 0.264737706 */, 19 }, + /* 7192 */ { MAD_F(0x043c9113) /* 0.264786794 */, 19 }, + /* 7193 */ { MAD_F(0x043cc48d) /* 0.264835884 */, 19 }, + /* 7194 */ { MAD_F(0x043cf807) /* 0.264884976 */, 19 }, + /* 7195 */ { MAD_F(0x043d2b82) /* 0.264934071 */, 19 }, + /* 7196 */ { MAD_F(0x043d5efd) /* 0.264983168 */, 19 }, + /* 7197 */ { MAD_F(0x043d9279) /* 0.265032268 */, 19 }, + /* 7198 */ { MAD_F(0x043dc5f6) /* 0.265081369 */, 19 }, + /* 7199 */ { MAD_F(0x043df973) /* 0.265130473 */, 19 }, + + /* 7200 */ { MAD_F(0x043e2cf1) /* 0.265179580 */, 19 }, + /* 7201 */ { MAD_F(0x043e6070) /* 0.265228688 */, 19 }, + /* 7202 */ { MAD_F(0x043e93ef) /* 0.265277799 */, 19 }, + /* 7203 */ { MAD_F(0x043ec76e) /* 0.265326912 */, 19 }, + /* 7204 */ { MAD_F(0x043efaef) /* 0.265376027 */, 19 }, + /* 7205 */ { MAD_F(0x043f2e6f) /* 0.265425145 */, 19 }, + /* 7206 */ { MAD_F(0x043f61f1) /* 0.265474264 */, 19 }, + /* 7207 */ { MAD_F(0x043f9573) /* 0.265523387 */, 19 }, + /* 7208 */ { MAD_F(0x043fc8f6) /* 0.265572511 */, 19 }, + /* 7209 */ { MAD_F(0x043ffc79) /* 0.265621638 */, 19 }, + /* 7210 */ { MAD_F(0x04402ffd) /* 0.265670766 */, 19 }, + /* 7211 */ { MAD_F(0x04406382) /* 0.265719898 */, 19 }, + /* 7212 */ { MAD_F(0x04409707) /* 0.265769031 */, 19 }, + /* 7213 */ { MAD_F(0x0440ca8d) /* 0.265818167 */, 19 }, + /* 7214 */ { MAD_F(0x0440fe13) /* 0.265867305 */, 19 }, + /* 7215 */ { MAD_F(0x0441319a) /* 0.265916445 */, 19 }, + + /* 7216 */ { MAD_F(0x04416522) /* 0.265965588 */, 19 }, + /* 7217 */ { MAD_F(0x044198aa) /* 0.266014732 */, 19 }, + /* 7218 */ { MAD_F(0x0441cc33) /* 0.266063880 */, 19 }, + /* 7219 */ { MAD_F(0x0441ffbc) /* 0.266113029 */, 19 }, + /* 7220 */ { MAD_F(0x04423346) /* 0.266162181 */, 19 }, + /* 7221 */ { MAD_F(0x044266d1) /* 0.266211334 */, 19 }, + /* 7222 */ { MAD_F(0x04429a5c) /* 0.266260491 */, 19 }, + /* 7223 */ { MAD_F(0x0442cde8) /* 0.266309649 */, 19 }, + /* 7224 */ { MAD_F(0x04430174) /* 0.266358810 */, 19 }, + /* 7225 */ { MAD_F(0x04433501) /* 0.266407973 */, 19 }, + /* 7226 */ { MAD_F(0x0443688f) /* 0.266457138 */, 19 }, + /* 7227 */ { MAD_F(0x04439c1d) /* 0.266506305 */, 19 }, + /* 7228 */ { MAD_F(0x0443cfac) /* 0.266555475 */, 19 }, + /* 7229 */ { MAD_F(0x0444033c) /* 0.266604647 */, 19 }, + /* 7230 */ { MAD_F(0x044436cc) /* 0.266653822 */, 19 }, + /* 7231 */ { MAD_F(0x04446a5d) /* 0.266702998 */, 19 }, + + /* 7232 */ { MAD_F(0x04449dee) /* 0.266752177 */, 19 }, + /* 7233 */ { MAD_F(0x0444d180) /* 0.266801358 */, 19 }, + /* 7234 */ { MAD_F(0x04450513) /* 0.266850541 */, 19 }, + /* 7235 */ { MAD_F(0x044538a6) /* 0.266899727 */, 19 }, + /* 7236 */ { MAD_F(0x04456c39) /* 0.266948915 */, 19 }, + /* 7237 */ { MAD_F(0x04459fce) /* 0.266998105 */, 19 }, + /* 7238 */ { MAD_F(0x0445d363) /* 0.267047298 */, 19 }, + /* 7239 */ { MAD_F(0x044606f8) /* 0.267096492 */, 19 }, + /* 7240 */ { MAD_F(0x04463a8f) /* 0.267145689 */, 19 }, + /* 7241 */ { MAD_F(0x04466e25) /* 0.267194888 */, 19 }, + /* 7242 */ { MAD_F(0x0446a1bd) /* 0.267244090 */, 19 }, + /* 7243 */ { MAD_F(0x0446d555) /* 0.267293294 */, 19 }, + /* 7244 */ { MAD_F(0x044708ee) /* 0.267342500 */, 19 }, + /* 7245 */ { MAD_F(0x04473c87) /* 0.267391708 */, 19 }, + /* 7246 */ { MAD_F(0x04477021) /* 0.267440919 */, 19 }, + /* 7247 */ { MAD_F(0x0447a3bb) /* 0.267490131 */, 19 }, + + /* 7248 */ { MAD_F(0x0447d756) /* 0.267539347 */, 19 }, + /* 7249 */ { MAD_F(0x04480af2) /* 0.267588564 */, 19 }, + /* 7250 */ { MAD_F(0x04483e8e) /* 0.267637783 */, 19 }, + /* 7251 */ { MAD_F(0x0448722b) /* 0.267687005 */, 19 }, + /* 7252 */ { MAD_F(0x0448a5c9) /* 0.267736229 */, 19 }, + /* 7253 */ { MAD_F(0x0448d967) /* 0.267785456 */, 19 }, + /* 7254 */ { MAD_F(0x04490d05) /* 0.267834685 */, 19 }, + /* 7255 */ { MAD_F(0x044940a5) /* 0.267883915 */, 19 }, + /* 7256 */ { MAD_F(0x04497445) /* 0.267933149 */, 19 }, + /* 7257 */ { MAD_F(0x0449a7e5) /* 0.267982384 */, 19 }, + /* 7258 */ { MAD_F(0x0449db86) /* 0.268031622 */, 19 }, + /* 7259 */ { MAD_F(0x044a0f28) /* 0.268080862 */, 19 }, + /* 7260 */ { MAD_F(0x044a42ca) /* 0.268130104 */, 19 }, + /* 7261 */ { MAD_F(0x044a766d) /* 0.268179349 */, 19 }, + /* 7262 */ { MAD_F(0x044aaa11) /* 0.268228595 */, 19 }, + /* 7263 */ { MAD_F(0x044addb5) /* 0.268277844 */, 19 }, + + /* 7264 */ { MAD_F(0x044b115a) /* 0.268327096 */, 19 }, + /* 7265 */ { MAD_F(0x044b44ff) /* 0.268376349 */, 19 }, + /* 7266 */ { MAD_F(0x044b78a5) /* 0.268425605 */, 19 }, + /* 7267 */ { MAD_F(0x044bac4c) /* 0.268474863 */, 19 }, + /* 7268 */ { MAD_F(0x044bdff3) /* 0.268524123 */, 19 }, + /* 7269 */ { MAD_F(0x044c139b) /* 0.268573386 */, 19 }, + /* 7270 */ { MAD_F(0x044c4743) /* 0.268622651 */, 19 }, + /* 7271 */ { MAD_F(0x044c7aec) /* 0.268671918 */, 19 }, + /* 7272 */ { MAD_F(0x044cae96) /* 0.268721187 */, 19 }, + /* 7273 */ { MAD_F(0x044ce240) /* 0.268770459 */, 19 }, + /* 7274 */ { MAD_F(0x044d15eb) /* 0.268819733 */, 19 }, + /* 7275 */ { MAD_F(0x044d4997) /* 0.268869009 */, 19 }, + /* 7276 */ { MAD_F(0x044d7d43) /* 0.268918287 */, 19 }, + /* 7277 */ { MAD_F(0x044db0ef) /* 0.268967568 */, 19 }, + /* 7278 */ { MAD_F(0x044de49d) /* 0.269016851 */, 19 }, + /* 7279 */ { MAD_F(0x044e184b) /* 0.269066136 */, 19 }, + + /* 7280 */ { MAD_F(0x044e4bf9) /* 0.269115423 */, 19 }, + /* 7281 */ { MAD_F(0x044e7fa8) /* 0.269164713 */, 19 }, + /* 7282 */ { MAD_F(0x044eb358) /* 0.269214005 */, 19 }, + /* 7283 */ { MAD_F(0x044ee708) /* 0.269263299 */, 19 }, + /* 7284 */ { MAD_F(0x044f1ab9) /* 0.269312595 */, 19 }, + /* 7285 */ { MAD_F(0x044f4e6b) /* 0.269361894 */, 19 }, + /* 7286 */ { MAD_F(0x044f821d) /* 0.269411195 */, 19 }, + /* 7287 */ { MAD_F(0x044fb5cf) /* 0.269460498 */, 19 }, + /* 7288 */ { MAD_F(0x044fe983) /* 0.269509804 */, 19 }, + /* 7289 */ { MAD_F(0x04501d37) /* 0.269559111 */, 19 }, + /* 7290 */ { MAD_F(0x045050eb) /* 0.269608421 */, 19 }, + /* 7291 */ { MAD_F(0x045084a0) /* 0.269657734 */, 19 }, + /* 7292 */ { MAD_F(0x0450b856) /* 0.269707048 */, 19 }, + /* 7293 */ { MAD_F(0x0450ec0d) /* 0.269756365 */, 19 }, + /* 7294 */ { MAD_F(0x04511fc4) /* 0.269805684 */, 19 }, + /* 7295 */ { MAD_F(0x0451537b) /* 0.269855005 */, 19 }, + + /* 7296 */ { MAD_F(0x04518733) /* 0.269904329 */, 19 }, + /* 7297 */ { MAD_F(0x0451baec) /* 0.269953654 */, 19 }, + /* 7298 */ { MAD_F(0x0451eea5) /* 0.270002982 */, 19 }, + /* 7299 */ { MAD_F(0x0452225f) /* 0.270052313 */, 19 }, + /* 7300 */ { MAD_F(0x0452561a) /* 0.270101645 */, 19 }, + /* 7301 */ { MAD_F(0x045289d5) /* 0.270150980 */, 19 }, + /* 7302 */ { MAD_F(0x0452bd91) /* 0.270200317 */, 19 }, + /* 7303 */ { MAD_F(0x0452f14d) /* 0.270249656 */, 19 }, + /* 7304 */ { MAD_F(0x0453250a) /* 0.270298998 */, 19 }, + /* 7305 */ { MAD_F(0x045358c8) /* 0.270348341 */, 19 }, + /* 7306 */ { MAD_F(0x04538c86) /* 0.270397687 */, 19 }, + /* 7307 */ { MAD_F(0x0453c045) /* 0.270447036 */, 19 }, + /* 7308 */ { MAD_F(0x0453f405) /* 0.270496386 */, 19 }, + /* 7309 */ { MAD_F(0x045427c5) /* 0.270545739 */, 19 }, + /* 7310 */ { MAD_F(0x04545b85) /* 0.270595094 */, 19 }, + /* 7311 */ { MAD_F(0x04548f46) /* 0.270644451 */, 19 }, + + /* 7312 */ { MAD_F(0x0454c308) /* 0.270693811 */, 19 }, + /* 7313 */ { MAD_F(0x0454f6cb) /* 0.270743173 */, 19 }, + /* 7314 */ { MAD_F(0x04552a8e) /* 0.270792537 */, 19 }, + /* 7315 */ { MAD_F(0x04555e51) /* 0.270841903 */, 19 }, + /* 7316 */ { MAD_F(0x04559216) /* 0.270891271 */, 19 }, + /* 7317 */ { MAD_F(0x0455c5db) /* 0.270940642 */, 19 }, + /* 7318 */ { MAD_F(0x0455f9a0) /* 0.270990015 */, 19 }, + /* 7319 */ { MAD_F(0x04562d66) /* 0.271039390 */, 19 }, + /* 7320 */ { MAD_F(0x0456612d) /* 0.271088768 */, 19 }, + /* 7321 */ { MAD_F(0x045694f4) /* 0.271138148 */, 19 }, + /* 7322 */ { MAD_F(0x0456c8bc) /* 0.271187530 */, 19 }, + /* 7323 */ { MAD_F(0x0456fc84) /* 0.271236914 */, 19 }, + /* 7324 */ { MAD_F(0x0457304e) /* 0.271286301 */, 19 }, + /* 7325 */ { MAD_F(0x04576417) /* 0.271335689 */, 19 }, + /* 7326 */ { MAD_F(0x045797e2) /* 0.271385080 */, 19 }, + /* 7327 */ { MAD_F(0x0457cbac) /* 0.271434474 */, 19 }, + + /* 7328 */ { MAD_F(0x0457ff78) /* 0.271483869 */, 19 }, + /* 7329 */ { MAD_F(0x04583344) /* 0.271533267 */, 19 }, + /* 7330 */ { MAD_F(0x04586711) /* 0.271582667 */, 19 }, + /* 7331 */ { MAD_F(0x04589ade) /* 0.271632069 */, 19 }, + /* 7332 */ { MAD_F(0x0458ceac) /* 0.271681474 */, 19 }, + /* 7333 */ { MAD_F(0x0459027b) /* 0.271730880 */, 19 }, + /* 7334 */ { MAD_F(0x0459364a) /* 0.271780289 */, 19 }, + /* 7335 */ { MAD_F(0x04596a19) /* 0.271829701 */, 19 }, + /* 7336 */ { MAD_F(0x04599dea) /* 0.271879114 */, 19 }, + /* 7337 */ { MAD_F(0x0459d1bb) /* 0.271928530 */, 19 }, + /* 7338 */ { MAD_F(0x045a058c) /* 0.271977948 */, 19 }, + /* 7339 */ { MAD_F(0x045a395e) /* 0.272027368 */, 19 }, + /* 7340 */ { MAD_F(0x045a6d31) /* 0.272076790 */, 19 }, + /* 7341 */ { MAD_F(0x045aa104) /* 0.272126215 */, 19 }, + /* 7342 */ { MAD_F(0x045ad4d8) /* 0.272175642 */, 19 }, + /* 7343 */ { MAD_F(0x045b08ad) /* 0.272225071 */, 19 }, + + /* 7344 */ { MAD_F(0x045b3c82) /* 0.272274503 */, 19 }, + /* 7345 */ { MAD_F(0x045b7058) /* 0.272323936 */, 19 }, + /* 7346 */ { MAD_F(0x045ba42e) /* 0.272373372 */, 19 }, + /* 7347 */ { MAD_F(0x045bd805) /* 0.272422810 */, 19 }, + /* 7348 */ { MAD_F(0x045c0bdd) /* 0.272472251 */, 19 }, + /* 7349 */ { MAD_F(0x045c3fb5) /* 0.272521693 */, 19 }, + /* 7350 */ { MAD_F(0x045c738e) /* 0.272571138 */, 19 }, + /* 7351 */ { MAD_F(0x045ca767) /* 0.272620585 */, 19 }, + /* 7352 */ { MAD_F(0x045cdb41) /* 0.272670035 */, 19 }, + /* 7353 */ { MAD_F(0x045d0f1b) /* 0.272719486 */, 19 }, + /* 7354 */ { MAD_F(0x045d42f7) /* 0.272768940 */, 19 }, + /* 7355 */ { MAD_F(0x045d76d2) /* 0.272818396 */, 19 }, + /* 7356 */ { MAD_F(0x045daaaf) /* 0.272867855 */, 19 }, + /* 7357 */ { MAD_F(0x045dde8c) /* 0.272917315 */, 19 }, + /* 7358 */ { MAD_F(0x045e1269) /* 0.272966778 */, 19 }, + /* 7359 */ { MAD_F(0x045e4647) /* 0.273016243 */, 19 }, + + /* 7360 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 19 }, + /* 7361 */ { MAD_F(0x045eae06) /* 0.273115180 */, 19 }, + /* 7362 */ { MAD_F(0x045ee1e6) /* 0.273164652 */, 19 }, + /* 7363 */ { MAD_F(0x045f15c6) /* 0.273214126 */, 19 }, + /* 7364 */ { MAD_F(0x045f49a7) /* 0.273263602 */, 19 }, + /* 7365 */ { MAD_F(0x045f7d89) /* 0.273313081 */, 19 }, + /* 7366 */ { MAD_F(0x045fb16c) /* 0.273362561 */, 19 }, + /* 7367 */ { MAD_F(0x045fe54f) /* 0.273412044 */, 19 }, + /* 7368 */ { MAD_F(0x04601932) /* 0.273461530 */, 19 }, + /* 7369 */ { MAD_F(0x04604d16) /* 0.273511017 */, 19 }, + /* 7370 */ { MAD_F(0x046080fb) /* 0.273560507 */, 19 }, + /* 7371 */ { MAD_F(0x0460b4e1) /* 0.273609999 */, 19 }, + /* 7372 */ { MAD_F(0x0460e8c7) /* 0.273659493 */, 19 }, + /* 7373 */ { MAD_F(0x04611cad) /* 0.273708989 */, 19 }, + /* 7374 */ { MAD_F(0x04615094) /* 0.273758488 */, 19 }, + /* 7375 */ { MAD_F(0x0461847c) /* 0.273807989 */, 19 }, + + /* 7376 */ { MAD_F(0x0461b864) /* 0.273857492 */, 19 }, + /* 7377 */ { MAD_F(0x0461ec4d) /* 0.273906997 */, 19 }, + /* 7378 */ { MAD_F(0x04622037) /* 0.273956505 */, 19 }, + /* 7379 */ { MAD_F(0x04625421) /* 0.274006015 */, 19 }, + /* 7380 */ { MAD_F(0x0462880c) /* 0.274055527 */, 19 }, + /* 7381 */ { MAD_F(0x0462bbf7) /* 0.274105041 */, 19 }, + /* 7382 */ { MAD_F(0x0462efe3) /* 0.274154558 */, 19 }, + /* 7383 */ { MAD_F(0x046323d0) /* 0.274204076 */, 19 }, + /* 7384 */ { MAD_F(0x046357bd) /* 0.274253597 */, 19 }, + /* 7385 */ { MAD_F(0x04638bab) /* 0.274303121 */, 19 }, + /* 7386 */ { MAD_F(0x0463bf99) /* 0.274352646 */, 19 }, + /* 7387 */ { MAD_F(0x0463f388) /* 0.274402174 */, 19 }, + /* 7388 */ { MAD_F(0x04642778) /* 0.274451704 */, 19 }, + /* 7389 */ { MAD_F(0x04645b68) /* 0.274501236 */, 19 }, + /* 7390 */ { MAD_F(0x04648f59) /* 0.274550771 */, 19 }, + /* 7391 */ { MAD_F(0x0464c34a) /* 0.274600307 */, 19 }, + + /* 7392 */ { MAD_F(0x0464f73c) /* 0.274649846 */, 19 }, + /* 7393 */ { MAD_F(0x04652b2f) /* 0.274699387 */, 19 }, + /* 7394 */ { MAD_F(0x04655f22) /* 0.274748931 */, 19 }, + /* 7395 */ { MAD_F(0x04659316) /* 0.274798476 */, 19 }, + /* 7396 */ { MAD_F(0x0465c70a) /* 0.274848024 */, 19 }, + /* 7397 */ { MAD_F(0x0465faff) /* 0.274897574 */, 19 }, + /* 7398 */ { MAD_F(0x04662ef5) /* 0.274947126 */, 19 }, + /* 7399 */ { MAD_F(0x046662eb) /* 0.274996681 */, 19 }, + /* 7400 */ { MAD_F(0x046696e2) /* 0.275046238 */, 19 }, + /* 7401 */ { MAD_F(0x0466cad9) /* 0.275095797 */, 19 }, + /* 7402 */ { MAD_F(0x0466fed1) /* 0.275145358 */, 19 }, + /* 7403 */ { MAD_F(0x046732ca) /* 0.275194921 */, 19 }, + /* 7404 */ { MAD_F(0x046766c3) /* 0.275244487 */, 19 }, + /* 7405 */ { MAD_F(0x04679abd) /* 0.275294055 */, 19 }, + /* 7406 */ { MAD_F(0x0467ceb7) /* 0.275343625 */, 19 }, + /* 7407 */ { MAD_F(0x046802b2) /* 0.275393198 */, 19 }, + + /* 7408 */ { MAD_F(0x046836ae) /* 0.275442772 */, 19 }, + /* 7409 */ { MAD_F(0x04686aaa) /* 0.275492349 */, 19 }, + /* 7410 */ { MAD_F(0x04689ea7) /* 0.275541928 */, 19 }, + /* 7411 */ { MAD_F(0x0468d2a4) /* 0.275591509 */, 19 }, + /* 7412 */ { MAD_F(0x046906a2) /* 0.275641093 */, 19 }, + /* 7413 */ { MAD_F(0x04693aa1) /* 0.275690679 */, 19 }, + /* 7414 */ { MAD_F(0x04696ea0) /* 0.275740267 */, 19 }, + /* 7415 */ { MAD_F(0x0469a2a0) /* 0.275789857 */, 19 }, + /* 7416 */ { MAD_F(0x0469d6a0) /* 0.275839449 */, 19 }, + /* 7417 */ { MAD_F(0x046a0aa1) /* 0.275889044 */, 19 }, + /* 7418 */ { MAD_F(0x046a3ea3) /* 0.275938641 */, 19 }, + /* 7419 */ { MAD_F(0x046a72a5) /* 0.275988240 */, 19 }, + /* 7420 */ { MAD_F(0x046aa6a8) /* 0.276037842 */, 19 }, + /* 7421 */ { MAD_F(0x046adaab) /* 0.276087445 */, 19 }, + /* 7422 */ { MAD_F(0x046b0eaf) /* 0.276137051 */, 19 }, + /* 7423 */ { MAD_F(0x046b42b3) /* 0.276186659 */, 19 }, + + /* 7424 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 19 }, + /* 7425 */ { MAD_F(0x046baabe) /* 0.276285882 */, 19 }, + /* 7426 */ { MAD_F(0x046bdec5) /* 0.276335497 */, 19 }, + /* 7427 */ { MAD_F(0x046c12cc) /* 0.276385113 */, 19 }, + /* 7428 */ { MAD_F(0x046c46d3) /* 0.276434733 */, 19 }, + /* 7429 */ { MAD_F(0x046c7adb) /* 0.276484354 */, 19 }, + /* 7430 */ { MAD_F(0x046caee4) /* 0.276533978 */, 19 }, + /* 7431 */ { MAD_F(0x046ce2ee) /* 0.276583604 */, 19 }, + /* 7432 */ { MAD_F(0x046d16f7) /* 0.276633232 */, 19 }, + /* 7433 */ { MAD_F(0x046d4b02) /* 0.276682862 */, 19 }, + /* 7434 */ { MAD_F(0x046d7f0d) /* 0.276732495 */, 19 }, + /* 7435 */ { MAD_F(0x046db319) /* 0.276782129 */, 19 }, + /* 7436 */ { MAD_F(0x046de725) /* 0.276831766 */, 19 }, + /* 7437 */ { MAD_F(0x046e1b32) /* 0.276881406 */, 19 }, + /* 7438 */ { MAD_F(0x046e4f40) /* 0.276931047 */, 19 }, + /* 7439 */ { MAD_F(0x046e834e) /* 0.276980691 */, 19 }, + + /* 7440 */ { MAD_F(0x046eb75c) /* 0.277030337 */, 19 }, + /* 7441 */ { MAD_F(0x046eeb6c) /* 0.277079985 */, 19 }, + /* 7442 */ { MAD_F(0x046f1f7c) /* 0.277129635 */, 19 }, + /* 7443 */ { MAD_F(0x046f538c) /* 0.277179288 */, 19 }, + /* 7444 */ { MAD_F(0x046f879d) /* 0.277228942 */, 19 }, + /* 7445 */ { MAD_F(0x046fbbaf) /* 0.277278600 */, 19 }, + /* 7446 */ { MAD_F(0x046fefc1) /* 0.277328259 */, 19 }, + /* 7447 */ { MAD_F(0x047023d4) /* 0.277377920 */, 19 }, + /* 7448 */ { MAD_F(0x047057e8) /* 0.277427584 */, 19 }, + /* 7449 */ { MAD_F(0x04708bfc) /* 0.277477250 */, 19 }, + /* 7450 */ { MAD_F(0x0470c011) /* 0.277526918 */, 19 }, + /* 7451 */ { MAD_F(0x0470f426) /* 0.277576588 */, 19 }, + /* 7452 */ { MAD_F(0x0471283c) /* 0.277626261 */, 19 }, + /* 7453 */ { MAD_F(0x04715c52) /* 0.277675936 */, 19 }, + /* 7454 */ { MAD_F(0x04719069) /* 0.277725613 */, 19 }, + /* 7455 */ { MAD_F(0x0471c481) /* 0.277775292 */, 19 }, + + /* 7456 */ { MAD_F(0x0471f899) /* 0.277824973 */, 19 }, + /* 7457 */ { MAD_F(0x04722cb2) /* 0.277874657 */, 19 }, + /* 7458 */ { MAD_F(0x047260cc) /* 0.277924343 */, 19 }, + /* 7459 */ { MAD_F(0x047294e6) /* 0.277974031 */, 19 }, + /* 7460 */ { MAD_F(0x0472c900) /* 0.278023722 */, 19 }, + /* 7461 */ { MAD_F(0x0472fd1b) /* 0.278073414 */, 19 }, + /* 7462 */ { MAD_F(0x04733137) /* 0.278123109 */, 19 }, + /* 7463 */ { MAD_F(0x04736554) /* 0.278172806 */, 19 }, + /* 7464 */ { MAD_F(0x04739971) /* 0.278222505 */, 19 }, + /* 7465 */ { MAD_F(0x0473cd8e) /* 0.278272207 */, 19 }, + /* 7466 */ { MAD_F(0x047401ad) /* 0.278321910 */, 19 }, + /* 7467 */ { MAD_F(0x047435cb) /* 0.278371616 */, 19 }, + /* 7468 */ { MAD_F(0x047469eb) /* 0.278421324 */, 19 }, + /* 7469 */ { MAD_F(0x04749e0b) /* 0.278471035 */, 19 }, + /* 7470 */ { MAD_F(0x0474d22c) /* 0.278520747 */, 19 }, + /* 7471 */ { MAD_F(0x0475064d) /* 0.278570462 */, 19 }, + + /* 7472 */ { MAD_F(0x04753a6f) /* 0.278620179 */, 19 }, + /* 7473 */ { MAD_F(0x04756e91) /* 0.278669898 */, 19 }, + /* 7474 */ { MAD_F(0x0475a2b4) /* 0.278719619 */, 19 }, + /* 7475 */ { MAD_F(0x0475d6d7) /* 0.278769343 */, 19 }, + /* 7476 */ { MAD_F(0x04760afc) /* 0.278819069 */, 19 }, + /* 7477 */ { MAD_F(0x04763f20) /* 0.278868797 */, 19 }, + /* 7478 */ { MAD_F(0x04767346) /* 0.278918527 */, 19 }, + /* 7479 */ { MAD_F(0x0476a76c) /* 0.278968260 */, 19 }, + /* 7480 */ { MAD_F(0x0476db92) /* 0.279017995 */, 19 }, + /* 7481 */ { MAD_F(0x04770fba) /* 0.279067731 */, 19 }, + /* 7482 */ { MAD_F(0x047743e1) /* 0.279117471 */, 19 }, + /* 7483 */ { MAD_F(0x0477780a) /* 0.279167212 */, 19 }, + /* 7484 */ { MAD_F(0x0477ac33) /* 0.279216956 */, 19 }, + /* 7485 */ { MAD_F(0x0477e05c) /* 0.279266701 */, 19 }, + /* 7486 */ { MAD_F(0x04781486) /* 0.279316449 */, 19 }, + /* 7487 */ { MAD_F(0x047848b1) /* 0.279366200 */, 19 }, + + /* 7488 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 19 }, + /* 7489 */ { MAD_F(0x0478b108) /* 0.279465707 */, 19 }, + /* 7490 */ { MAD_F(0x0478e535) /* 0.279515464 */, 19 }, + /* 7491 */ { MAD_F(0x04791962) /* 0.279565223 */, 19 }, + /* 7492 */ { MAD_F(0x04794d8f) /* 0.279614984 */, 19 }, + /* 7493 */ { MAD_F(0x047981be) /* 0.279664748 */, 19 }, + /* 7494 */ { MAD_F(0x0479b5ed) /* 0.279714513 */, 19 }, + /* 7495 */ { MAD_F(0x0479ea1c) /* 0.279764281 */, 19 }, + /* 7496 */ { MAD_F(0x047a1e4c) /* 0.279814051 */, 19 }, + /* 7497 */ { MAD_F(0x047a527d) /* 0.279863824 */, 19 }, + /* 7498 */ { MAD_F(0x047a86ae) /* 0.279913598 */, 19 }, + /* 7499 */ { MAD_F(0x047abae0) /* 0.279963375 */, 19 }, + /* 7500 */ { MAD_F(0x047aef12) /* 0.280013154 */, 19 }, + /* 7501 */ { MAD_F(0x047b2346) /* 0.280062935 */, 19 }, + /* 7502 */ { MAD_F(0x047b5779) /* 0.280112719 */, 19 }, + /* 7503 */ { MAD_F(0x047b8bad) /* 0.280162504 */, 19 }, + + /* 7504 */ { MAD_F(0x047bbfe2) /* 0.280212292 */, 19 }, + /* 7505 */ { MAD_F(0x047bf418) /* 0.280262082 */, 19 }, + /* 7506 */ { MAD_F(0x047c284e) /* 0.280311875 */, 19 }, + /* 7507 */ { MAD_F(0x047c5c84) /* 0.280361669 */, 19 }, + /* 7508 */ { MAD_F(0x047c90bb) /* 0.280411466 */, 19 }, + /* 7509 */ { MAD_F(0x047cc4f3) /* 0.280461265 */, 19 }, + /* 7510 */ { MAD_F(0x047cf92c) /* 0.280511066 */, 19 }, + /* 7511 */ { MAD_F(0x047d2d65) /* 0.280560869 */, 19 }, + /* 7512 */ { MAD_F(0x047d619e) /* 0.280610675 */, 19 }, + /* 7513 */ { MAD_F(0x047d95d8) /* 0.280660483 */, 19 }, + /* 7514 */ { MAD_F(0x047dca13) /* 0.280710292 */, 19 }, + /* 7515 */ { MAD_F(0x047dfe4e) /* 0.280760105 */, 19 }, + /* 7516 */ { MAD_F(0x047e328a) /* 0.280809919 */, 19 }, + /* 7517 */ { MAD_F(0x047e66c7) /* 0.280859736 */, 19 }, + /* 7518 */ { MAD_F(0x047e9b04) /* 0.280909554 */, 19 }, + /* 7519 */ { MAD_F(0x047ecf42) /* 0.280959375 */, 19 }, + + /* 7520 */ { MAD_F(0x047f0380) /* 0.281009199 */, 19 }, + /* 7521 */ { MAD_F(0x047f37bf) /* 0.281059024 */, 19 }, + /* 7522 */ { MAD_F(0x047f6bff) /* 0.281108852 */, 19 }, + /* 7523 */ { MAD_F(0x047fa03f) /* 0.281158682 */, 19 }, + /* 7524 */ { MAD_F(0x047fd47f) /* 0.281208514 */, 19 }, + /* 7525 */ { MAD_F(0x048008c1) /* 0.281258348 */, 19 }, + /* 7526 */ { MAD_F(0x04803d02) /* 0.281308184 */, 19 }, + /* 7527 */ { MAD_F(0x04807145) /* 0.281358023 */, 19 }, + /* 7528 */ { MAD_F(0x0480a588) /* 0.281407864 */, 19 }, + /* 7529 */ { MAD_F(0x0480d9cc) /* 0.281457707 */, 19 }, + /* 7530 */ { MAD_F(0x04810e10) /* 0.281507552 */, 19 }, + /* 7531 */ { MAD_F(0x04814255) /* 0.281557400 */, 19 }, + /* 7532 */ { MAD_F(0x0481769a) /* 0.281607250 */, 19 }, + /* 7533 */ { MAD_F(0x0481aae0) /* 0.281657101 */, 19 }, + /* 7534 */ { MAD_F(0x0481df27) /* 0.281706956 */, 19 }, + /* 7535 */ { MAD_F(0x0482136e) /* 0.281756812 */, 19 }, + + /* 7536 */ { MAD_F(0x048247b6) /* 0.281806670 */, 19 }, + /* 7537 */ { MAD_F(0x04827bfe) /* 0.281856531 */, 19 }, + /* 7538 */ { MAD_F(0x0482b047) /* 0.281906394 */, 19 }, + /* 7539 */ { MAD_F(0x0482e491) /* 0.281956259 */, 19 }, + /* 7540 */ { MAD_F(0x048318db) /* 0.282006127 */, 19 }, + /* 7541 */ { MAD_F(0x04834d26) /* 0.282055996 */, 19 }, + /* 7542 */ { MAD_F(0x04838171) /* 0.282105868 */, 19 }, + /* 7543 */ { MAD_F(0x0483b5bd) /* 0.282155742 */, 19 }, + /* 7544 */ { MAD_F(0x0483ea0a) /* 0.282205618 */, 19 }, + /* 7545 */ { MAD_F(0x04841e57) /* 0.282255496 */, 19 }, + /* 7546 */ { MAD_F(0x048452a4) /* 0.282305377 */, 19 }, + /* 7547 */ { MAD_F(0x048486f3) /* 0.282355260 */, 19 }, + /* 7548 */ { MAD_F(0x0484bb42) /* 0.282405145 */, 19 }, + /* 7549 */ { MAD_F(0x0484ef91) /* 0.282455032 */, 19 }, + /* 7550 */ { MAD_F(0x048523e1) /* 0.282504921 */, 19 }, + /* 7551 */ { MAD_F(0x04855832) /* 0.282554813 */, 19 }, + + /* 7552 */ { MAD_F(0x04858c83) /* 0.282604707 */, 19 }, + /* 7553 */ { MAD_F(0x0485c0d5) /* 0.282654603 */, 19 }, + /* 7554 */ { MAD_F(0x0485f527) /* 0.282704501 */, 19 }, + /* 7555 */ { MAD_F(0x0486297a) /* 0.282754401 */, 19 }, + /* 7556 */ { MAD_F(0x04865dce) /* 0.282804304 */, 19 }, + /* 7557 */ { MAD_F(0x04869222) /* 0.282854209 */, 19 }, + /* 7558 */ { MAD_F(0x0486c677) /* 0.282904116 */, 19 }, + /* 7559 */ { MAD_F(0x0486facc) /* 0.282954025 */, 19 }, + /* 7560 */ { MAD_F(0x04872f22) /* 0.283003936 */, 19 }, + /* 7561 */ { MAD_F(0x04876379) /* 0.283053850 */, 19 }, + /* 7562 */ { MAD_F(0x048797d0) /* 0.283103766 */, 19 }, + /* 7563 */ { MAD_F(0x0487cc28) /* 0.283153684 */, 19 }, + /* 7564 */ { MAD_F(0x04880080) /* 0.283203604 */, 19 }, + /* 7565 */ { MAD_F(0x048834d9) /* 0.283253527 */, 19 }, + /* 7566 */ { MAD_F(0x04886933) /* 0.283303451 */, 19 }, + /* 7567 */ { MAD_F(0x04889d8d) /* 0.283353378 */, 19 }, + + /* 7568 */ { MAD_F(0x0488d1e8) /* 0.283403307 */, 19 }, + /* 7569 */ { MAD_F(0x04890643) /* 0.283453238 */, 19 }, + /* 7570 */ { MAD_F(0x04893a9f) /* 0.283503172 */, 19 }, + /* 7571 */ { MAD_F(0x04896efb) /* 0.283553107 */, 19 }, + /* 7572 */ { MAD_F(0x0489a358) /* 0.283603045 */, 19 }, + /* 7573 */ { MAD_F(0x0489d7b6) /* 0.283652985 */, 19 }, + /* 7574 */ { MAD_F(0x048a0c14) /* 0.283702927 */, 19 }, + /* 7575 */ { MAD_F(0x048a4073) /* 0.283752872 */, 19 }, + /* 7576 */ { MAD_F(0x048a74d3) /* 0.283802818 */, 19 }, + /* 7577 */ { MAD_F(0x048aa933) /* 0.283852767 */, 19 }, + /* 7578 */ { MAD_F(0x048add93) /* 0.283902718 */, 19 }, + /* 7579 */ { MAD_F(0x048b11f5) /* 0.283952671 */, 19 }, + /* 7580 */ { MAD_F(0x048b4656) /* 0.284002627 */, 19 }, + /* 7581 */ { MAD_F(0x048b7ab9) /* 0.284052584 */, 19 }, + /* 7582 */ { MAD_F(0x048baf1c) /* 0.284102544 */, 19 }, + /* 7583 */ { MAD_F(0x048be37f) /* 0.284152506 */, 19 }, + + /* 7584 */ { MAD_F(0x048c17e3) /* 0.284202470 */, 19 }, + /* 7585 */ { MAD_F(0x048c4c48) /* 0.284252436 */, 19 }, + /* 7586 */ { MAD_F(0x048c80ad) /* 0.284302405 */, 19 }, + /* 7587 */ { MAD_F(0x048cb513) /* 0.284352376 */, 19 }, + /* 7588 */ { MAD_F(0x048ce97a) /* 0.284402349 */, 19 }, + /* 7589 */ { MAD_F(0x048d1de1) /* 0.284452324 */, 19 }, + /* 7590 */ { MAD_F(0x048d5249) /* 0.284502301 */, 19 }, + /* 7591 */ { MAD_F(0x048d86b1) /* 0.284552281 */, 19 }, + /* 7592 */ { MAD_F(0x048dbb1a) /* 0.284602263 */, 19 }, + /* 7593 */ { MAD_F(0x048def83) /* 0.284652246 */, 19 }, + /* 7594 */ { MAD_F(0x048e23ed) /* 0.284702233 */, 19 }, + /* 7595 */ { MAD_F(0x048e5858) /* 0.284752221 */, 19 }, + /* 7596 */ { MAD_F(0x048e8cc3) /* 0.284802211 */, 19 }, + /* 7597 */ { MAD_F(0x048ec12f) /* 0.284852204 */, 19 }, + /* 7598 */ { MAD_F(0x048ef59b) /* 0.284902199 */, 19 }, + /* 7599 */ { MAD_F(0x048f2a08) /* 0.284952196 */, 19 }, + + /* 7600 */ { MAD_F(0x048f5e76) /* 0.285002195 */, 19 }, + /* 7601 */ { MAD_F(0x048f92e4) /* 0.285052197 */, 19 }, + /* 7602 */ { MAD_F(0x048fc753) /* 0.285102201 */, 19 }, + /* 7603 */ { MAD_F(0x048ffbc2) /* 0.285152206 */, 19 }, + /* 7604 */ { MAD_F(0x04903032) /* 0.285202214 */, 19 }, + /* 7605 */ { MAD_F(0x049064a3) /* 0.285252225 */, 19 }, + /* 7606 */ { MAD_F(0x04909914) /* 0.285302237 */, 19 }, + /* 7607 */ { MAD_F(0x0490cd86) /* 0.285352252 */, 19 }, + /* 7608 */ { MAD_F(0x049101f8) /* 0.285402269 */, 19 }, + /* 7609 */ { MAD_F(0x0491366b) /* 0.285452288 */, 19 }, + /* 7610 */ { MAD_F(0x04916ade) /* 0.285502309 */, 19 }, + /* 7611 */ { MAD_F(0x04919f52) /* 0.285552332 */, 19 }, + /* 7612 */ { MAD_F(0x0491d3c7) /* 0.285602358 */, 19 }, + /* 7613 */ { MAD_F(0x0492083c) /* 0.285652386 */, 19 }, + /* 7614 */ { MAD_F(0x04923cb2) /* 0.285702416 */, 19 }, + /* 7615 */ { MAD_F(0x04927128) /* 0.285752448 */, 19 }, + + /* 7616 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 19 }, + /* 7617 */ { MAD_F(0x0492da17) /* 0.285852519 */, 19 }, + /* 7618 */ { MAD_F(0x04930e8f) /* 0.285902557 */, 19 }, + /* 7619 */ { MAD_F(0x04934308) /* 0.285952598 */, 19 }, + /* 7620 */ { MAD_F(0x04937781) /* 0.286002641 */, 19 }, + /* 7621 */ { MAD_F(0x0493abfb) /* 0.286052687 */, 19 }, + /* 7622 */ { MAD_F(0x0493e076) /* 0.286102734 */, 19 }, + /* 7623 */ { MAD_F(0x049414f1) /* 0.286152784 */, 19 }, + /* 7624 */ { MAD_F(0x0494496c) /* 0.286202836 */, 19 }, + /* 7625 */ { MAD_F(0x04947de9) /* 0.286252890 */, 19 }, + /* 7626 */ { MAD_F(0x0494b266) /* 0.286302946 */, 19 }, + /* 7627 */ { MAD_F(0x0494e6e3) /* 0.286353005 */, 19 }, + /* 7628 */ { MAD_F(0x04951b61) /* 0.286403065 */, 19 }, + /* 7629 */ { MAD_F(0x04954fe0) /* 0.286453128 */, 19 }, + /* 7630 */ { MAD_F(0x0495845f) /* 0.286503193 */, 19 }, + /* 7631 */ { MAD_F(0x0495b8df) /* 0.286553260 */, 19 }, + + /* 7632 */ { MAD_F(0x0495ed5f) /* 0.286603329 */, 19 }, + /* 7633 */ { MAD_F(0x049621e0) /* 0.286653401 */, 19 }, + /* 7634 */ { MAD_F(0x04965662) /* 0.286703475 */, 19 }, + /* 7635 */ { MAD_F(0x04968ae4) /* 0.286753551 */, 19 }, + /* 7636 */ { MAD_F(0x0496bf67) /* 0.286803629 */, 19 }, + /* 7637 */ { MAD_F(0x0496f3ea) /* 0.286853709 */, 19 }, + /* 7638 */ { MAD_F(0x0497286e) /* 0.286903792 */, 19 }, + /* 7639 */ { MAD_F(0x04975cf2) /* 0.286953876 */, 19 }, + /* 7640 */ { MAD_F(0x04979177) /* 0.287003963 */, 19 }, + /* 7641 */ { MAD_F(0x0497c5fd) /* 0.287054052 */, 19 }, + /* 7642 */ { MAD_F(0x0497fa83) /* 0.287104143 */, 19 }, + /* 7643 */ { MAD_F(0x04982f0a) /* 0.287154237 */, 19 }, + /* 7644 */ { MAD_F(0x04986392) /* 0.287204332 */, 19 }, + /* 7645 */ { MAD_F(0x0498981a) /* 0.287254430 */, 19 }, + /* 7646 */ { MAD_F(0x0498cca2) /* 0.287304530 */, 19 }, + /* 7647 */ { MAD_F(0x0499012c) /* 0.287354632 */, 19 }, + + /* 7648 */ { MAD_F(0x049935b5) /* 0.287404737 */, 19 }, + /* 7649 */ { MAD_F(0x04996a40) /* 0.287454843 */, 19 }, + /* 7650 */ { MAD_F(0x04999ecb) /* 0.287504952 */, 19 }, + /* 7651 */ { MAD_F(0x0499d356) /* 0.287555063 */, 19 }, + /* 7652 */ { MAD_F(0x049a07e2) /* 0.287605176 */, 19 }, + /* 7653 */ { MAD_F(0x049a3c6f) /* 0.287655291 */, 19 }, + /* 7654 */ { MAD_F(0x049a70fc) /* 0.287705409 */, 19 }, + /* 7655 */ { MAD_F(0x049aa58a) /* 0.287755528 */, 19 }, + /* 7656 */ { MAD_F(0x049ada19) /* 0.287805650 */, 19 }, + /* 7657 */ { MAD_F(0x049b0ea8) /* 0.287855774 */, 19 }, + /* 7658 */ { MAD_F(0x049b4337) /* 0.287905900 */, 19 }, + /* 7659 */ { MAD_F(0x049b77c8) /* 0.287956028 */, 19 }, + /* 7660 */ { MAD_F(0x049bac58) /* 0.288006159 */, 19 }, + /* 7661 */ { MAD_F(0x049be0ea) /* 0.288056292 */, 19 }, + /* 7662 */ { MAD_F(0x049c157c) /* 0.288106427 */, 19 }, + /* 7663 */ { MAD_F(0x049c4a0e) /* 0.288156564 */, 19 }, + + /* 7664 */ { MAD_F(0x049c7ea1) /* 0.288206703 */, 19 }, + /* 7665 */ { MAD_F(0x049cb335) /* 0.288256844 */, 19 }, + /* 7666 */ { MAD_F(0x049ce7ca) /* 0.288306988 */, 19 }, + /* 7667 */ { MAD_F(0x049d1c5e) /* 0.288357134 */, 19 }, + /* 7668 */ { MAD_F(0x049d50f4) /* 0.288407282 */, 19 }, + /* 7669 */ { MAD_F(0x049d858a) /* 0.288457432 */, 19 }, + /* 7670 */ { MAD_F(0x049dba21) /* 0.288507584 */, 19 }, + /* 7671 */ { MAD_F(0x049deeb8) /* 0.288557739 */, 19 }, + /* 7672 */ { MAD_F(0x049e2350) /* 0.288607895 */, 19 }, + /* 7673 */ { MAD_F(0x049e57e8) /* 0.288658054 */, 19 }, + /* 7674 */ { MAD_F(0x049e8c81) /* 0.288708215 */, 19 }, + /* 7675 */ { MAD_F(0x049ec11b) /* 0.288758379 */, 19 }, + /* 7676 */ { MAD_F(0x049ef5b5) /* 0.288808544 */, 19 }, + /* 7677 */ { MAD_F(0x049f2a50) /* 0.288858712 */, 19 }, + /* 7678 */ { MAD_F(0x049f5eeb) /* 0.288908881 */, 19 }, + /* 7679 */ { MAD_F(0x049f9387) /* 0.288959053 */, 19 }, + + /* 7680 */ { MAD_F(0x049fc824) /* 0.289009227 */, 19 }, + /* 7681 */ { MAD_F(0x049ffcc1) /* 0.289059404 */, 19 }, + /* 7682 */ { MAD_F(0x04a0315e) /* 0.289109582 */, 19 }, + /* 7683 */ { MAD_F(0x04a065fd) /* 0.289159763 */, 19 }, + /* 7684 */ { MAD_F(0x04a09a9b) /* 0.289209946 */, 19 }, + /* 7685 */ { MAD_F(0x04a0cf3b) /* 0.289260131 */, 19 }, + /* 7686 */ { MAD_F(0x04a103db) /* 0.289310318 */, 19 }, + /* 7687 */ { MAD_F(0x04a1387b) /* 0.289360507 */, 19 }, + /* 7688 */ { MAD_F(0x04a16d1d) /* 0.289410699 */, 19 }, + /* 7689 */ { MAD_F(0x04a1a1be) /* 0.289460893 */, 19 }, + /* 7690 */ { MAD_F(0x04a1d661) /* 0.289511088 */, 19 }, + /* 7691 */ { MAD_F(0x04a20b04) /* 0.289561287 */, 19 }, + /* 7692 */ { MAD_F(0x04a23fa7) /* 0.289611487 */, 19 }, + /* 7693 */ { MAD_F(0x04a2744b) /* 0.289661689 */, 19 }, + /* 7694 */ { MAD_F(0x04a2a8f0) /* 0.289711894 */, 19 }, + /* 7695 */ { MAD_F(0x04a2dd95) /* 0.289762101 */, 19 }, + + /* 7696 */ { MAD_F(0x04a3123b) /* 0.289812309 */, 19 }, + /* 7697 */ { MAD_F(0x04a346e2) /* 0.289862521 */, 19 }, + /* 7698 */ { MAD_F(0x04a37b89) /* 0.289912734 */, 19 }, + /* 7699 */ { MAD_F(0x04a3b030) /* 0.289962949 */, 19 }, + /* 7700 */ { MAD_F(0x04a3e4d8) /* 0.290013167 */, 19 }, + /* 7701 */ { MAD_F(0x04a41981) /* 0.290063387 */, 19 }, + /* 7702 */ { MAD_F(0x04a44e2b) /* 0.290113609 */, 19 }, + /* 7703 */ { MAD_F(0x04a482d5) /* 0.290163833 */, 19 }, + /* 7704 */ { MAD_F(0x04a4b77f) /* 0.290214059 */, 19 }, + /* 7705 */ { MAD_F(0x04a4ec2a) /* 0.290264288 */, 19 }, + /* 7706 */ { MAD_F(0x04a520d6) /* 0.290314519 */, 19 }, + /* 7707 */ { MAD_F(0x04a55582) /* 0.290364751 */, 19 }, + /* 7708 */ { MAD_F(0x04a58a2f) /* 0.290414986 */, 19 }, + /* 7709 */ { MAD_F(0x04a5bedd) /* 0.290465224 */, 19 }, + /* 7710 */ { MAD_F(0x04a5f38b) /* 0.290515463 */, 19 }, + /* 7711 */ { MAD_F(0x04a62839) /* 0.290565705 */, 19 }, + + /* 7712 */ { MAD_F(0x04a65ce8) /* 0.290615948 */, 19 }, + /* 7713 */ { MAD_F(0x04a69198) /* 0.290666194 */, 19 }, + /* 7714 */ { MAD_F(0x04a6c648) /* 0.290716442 */, 19 }, + /* 7715 */ { MAD_F(0x04a6faf9) /* 0.290766692 */, 19 }, + /* 7716 */ { MAD_F(0x04a72fab) /* 0.290816945 */, 19 }, + /* 7717 */ { MAD_F(0x04a7645d) /* 0.290867199 */, 19 }, + /* 7718 */ { MAD_F(0x04a79910) /* 0.290917456 */, 19 }, + /* 7719 */ { MAD_F(0x04a7cdc3) /* 0.290967715 */, 19 }, + /* 7720 */ { MAD_F(0x04a80277) /* 0.291017976 */, 19 }, + /* 7721 */ { MAD_F(0x04a8372b) /* 0.291068239 */, 19 }, + /* 7722 */ { MAD_F(0x04a86be0) /* 0.291118505 */, 19 }, + /* 7723 */ { MAD_F(0x04a8a096) /* 0.291168772 */, 19 }, + /* 7724 */ { MAD_F(0x04a8d54c) /* 0.291219042 */, 19 }, + /* 7725 */ { MAD_F(0x04a90a03) /* 0.291269314 */, 19 }, + /* 7726 */ { MAD_F(0x04a93eba) /* 0.291319588 */, 19 }, + /* 7727 */ { MAD_F(0x04a97372) /* 0.291369865 */, 19 }, + + /* 7728 */ { MAD_F(0x04a9a82b) /* 0.291420143 */, 19 }, + /* 7729 */ { MAD_F(0x04a9dce4) /* 0.291470424 */, 19 }, + /* 7730 */ { MAD_F(0x04aa119d) /* 0.291520706 */, 19 }, + /* 7731 */ { MAD_F(0x04aa4658) /* 0.291570991 */, 19 }, + /* 7732 */ { MAD_F(0x04aa7b13) /* 0.291621278 */, 19 }, + /* 7733 */ { MAD_F(0x04aaafce) /* 0.291671568 */, 19 }, + /* 7734 */ { MAD_F(0x04aae48a) /* 0.291721859 */, 19 }, + /* 7735 */ { MAD_F(0x04ab1947) /* 0.291772153 */, 19 }, + /* 7736 */ { MAD_F(0x04ab4e04) /* 0.291822449 */, 19 }, + /* 7737 */ { MAD_F(0x04ab82c2) /* 0.291872747 */, 19 }, + /* 7738 */ { MAD_F(0x04abb780) /* 0.291923047 */, 19 }, + /* 7739 */ { MAD_F(0x04abec3f) /* 0.291973349 */, 19 }, + /* 7740 */ { MAD_F(0x04ac20fe) /* 0.292023653 */, 19 }, + /* 7741 */ { MAD_F(0x04ac55be) /* 0.292073960 */, 19 }, + /* 7742 */ { MAD_F(0x04ac8a7f) /* 0.292124269 */, 19 }, + /* 7743 */ { MAD_F(0x04acbf40) /* 0.292174580 */, 19 }, + + /* 7744 */ { MAD_F(0x04acf402) /* 0.292224893 */, 19 }, + /* 7745 */ { MAD_F(0x04ad28c5) /* 0.292275208 */, 19 }, + /* 7746 */ { MAD_F(0x04ad5d88) /* 0.292325526 */, 19 }, + /* 7747 */ { MAD_F(0x04ad924b) /* 0.292375845 */, 19 }, + /* 7748 */ { MAD_F(0x04adc70f) /* 0.292426167 */, 19 }, + /* 7749 */ { MAD_F(0x04adfbd4) /* 0.292476491 */, 19 }, + /* 7750 */ { MAD_F(0x04ae3099) /* 0.292526817 */, 19 }, + /* 7751 */ { MAD_F(0x04ae655f) /* 0.292577145 */, 19 }, + /* 7752 */ { MAD_F(0x04ae9a26) /* 0.292627476 */, 19 }, + /* 7753 */ { MAD_F(0x04aeceed) /* 0.292677808 */, 19 }, + /* 7754 */ { MAD_F(0x04af03b4) /* 0.292728143 */, 19 }, + /* 7755 */ { MAD_F(0x04af387d) /* 0.292778480 */, 19 }, + /* 7756 */ { MAD_F(0x04af6d45) /* 0.292828819 */, 19 }, + /* 7757 */ { MAD_F(0x04afa20f) /* 0.292879160 */, 19 }, + /* 7758 */ { MAD_F(0x04afd6d9) /* 0.292929504 */, 19 }, + /* 7759 */ { MAD_F(0x04b00ba3) /* 0.292979849 */, 19 }, + + /* 7760 */ { MAD_F(0x04b0406e) /* 0.293030197 */, 19 }, + /* 7761 */ { MAD_F(0x04b0753a) /* 0.293080547 */, 19 }, + /* 7762 */ { MAD_F(0x04b0aa06) /* 0.293130899 */, 19 }, + /* 7763 */ { MAD_F(0x04b0ded3) /* 0.293181253 */, 19 }, + /* 7764 */ { MAD_F(0x04b113a1) /* 0.293231610 */, 19 }, + /* 7765 */ { MAD_F(0x04b1486f) /* 0.293281968 */, 19 }, + /* 7766 */ { MAD_F(0x04b17d3d) /* 0.293332329 */, 19 }, + /* 7767 */ { MAD_F(0x04b1b20c) /* 0.293382692 */, 19 }, + /* 7768 */ { MAD_F(0x04b1e6dc) /* 0.293433057 */, 19 }, + /* 7769 */ { MAD_F(0x04b21bad) /* 0.293483424 */, 19 }, + /* 7770 */ { MAD_F(0x04b2507d) /* 0.293533794 */, 19 }, + /* 7771 */ { MAD_F(0x04b2854f) /* 0.293584165 */, 19 }, + /* 7772 */ { MAD_F(0x04b2ba21) /* 0.293634539 */, 19 }, + /* 7773 */ { MAD_F(0x04b2eef4) /* 0.293684915 */, 19 }, + /* 7774 */ { MAD_F(0x04b323c7) /* 0.293735293 */, 19 }, + /* 7775 */ { MAD_F(0x04b3589b) /* 0.293785673 */, 19 }, + + /* 7776 */ { MAD_F(0x04b38d6f) /* 0.293836055 */, 19 }, + /* 7777 */ { MAD_F(0x04b3c244) /* 0.293886440 */, 19 }, + /* 7778 */ { MAD_F(0x04b3f71a) /* 0.293936826 */, 19 }, + /* 7779 */ { MAD_F(0x04b42bf0) /* 0.293987215 */, 19 }, + /* 7780 */ { MAD_F(0x04b460c7) /* 0.294037606 */, 19 }, + /* 7781 */ { MAD_F(0x04b4959e) /* 0.294087999 */, 19 }, + /* 7782 */ { MAD_F(0x04b4ca76) /* 0.294138395 */, 19 }, + /* 7783 */ { MAD_F(0x04b4ff4e) /* 0.294188792 */, 19 }, + /* 7784 */ { MAD_F(0x04b53427) /* 0.294239192 */, 19 }, + /* 7785 */ { MAD_F(0x04b56901) /* 0.294289593 */, 19 }, + /* 7786 */ { MAD_F(0x04b59ddb) /* 0.294339997 */, 19 }, + /* 7787 */ { MAD_F(0x04b5d2b6) /* 0.294390403 */, 19 }, + /* 7788 */ { MAD_F(0x04b60791) /* 0.294440812 */, 19 }, + /* 7789 */ { MAD_F(0x04b63c6d) /* 0.294491222 */, 19 }, + /* 7790 */ { MAD_F(0x04b6714a) /* 0.294541635 */, 19 }, + /* 7791 */ { MAD_F(0x04b6a627) /* 0.294592049 */, 19 }, + + /* 7792 */ { MAD_F(0x04b6db05) /* 0.294642466 */, 19 }, + /* 7793 */ { MAD_F(0x04b70fe3) /* 0.294692885 */, 19 }, + /* 7794 */ { MAD_F(0x04b744c2) /* 0.294743306 */, 19 }, + /* 7795 */ { MAD_F(0x04b779a1) /* 0.294793730 */, 19 }, + /* 7796 */ { MAD_F(0x04b7ae81) /* 0.294844155 */, 19 }, + /* 7797 */ { MAD_F(0x04b7e362) /* 0.294894583 */, 19 }, + /* 7798 */ { MAD_F(0x04b81843) /* 0.294945013 */, 19 }, + /* 7799 */ { MAD_F(0x04b84d24) /* 0.294995445 */, 19 }, + /* 7800 */ { MAD_F(0x04b88207) /* 0.295045879 */, 19 }, + /* 7801 */ { MAD_F(0x04b8b6ea) /* 0.295096315 */, 19 }, + /* 7802 */ { MAD_F(0x04b8ebcd) /* 0.295146753 */, 19 }, + /* 7803 */ { MAD_F(0x04b920b1) /* 0.295197194 */, 19 }, + /* 7804 */ { MAD_F(0x04b95596) /* 0.295247637 */, 19 }, + /* 7805 */ { MAD_F(0x04b98a7b) /* 0.295298082 */, 19 }, + /* 7806 */ { MAD_F(0x04b9bf61) /* 0.295348529 */, 19 }, + /* 7807 */ { MAD_F(0x04b9f447) /* 0.295398978 */, 19 }, + + /* 7808 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 19 }, + /* 7809 */ { MAD_F(0x04ba5e16) /* 0.295499883 */, 19 }, + /* 7810 */ { MAD_F(0x04ba92fe) /* 0.295550338 */, 19 }, + /* 7811 */ { MAD_F(0x04bac7e6) /* 0.295600796 */, 19 }, + /* 7812 */ { MAD_F(0x04bafcd0) /* 0.295651256 */, 19 }, + /* 7813 */ { MAD_F(0x04bb31b9) /* 0.295701718 */, 19 }, + /* 7814 */ { MAD_F(0x04bb66a4) /* 0.295752183 */, 19 }, + /* 7815 */ { MAD_F(0x04bb9b8f) /* 0.295802649 */, 19 }, + /* 7816 */ { MAD_F(0x04bbd07a) /* 0.295853118 */, 19 }, + /* 7817 */ { MAD_F(0x04bc0566) /* 0.295903588 */, 19 }, + /* 7818 */ { MAD_F(0x04bc3a53) /* 0.295954061 */, 19 }, + /* 7819 */ { MAD_F(0x04bc6f40) /* 0.296004536 */, 19 }, + /* 7820 */ { MAD_F(0x04bca42e) /* 0.296055013 */, 19 }, + /* 7821 */ { MAD_F(0x04bcd91d) /* 0.296105493 */, 19 }, + /* 7822 */ { MAD_F(0x04bd0e0c) /* 0.296155974 */, 19 }, + /* 7823 */ { MAD_F(0x04bd42fb) /* 0.296206458 */, 19 }, + + /* 7824 */ { MAD_F(0x04bd77ec) /* 0.296256944 */, 19 }, + /* 7825 */ { MAD_F(0x04bdacdc) /* 0.296307432 */, 19 }, + /* 7826 */ { MAD_F(0x04bde1ce) /* 0.296357922 */, 19 }, + /* 7827 */ { MAD_F(0x04be16c0) /* 0.296408414 */, 19 }, + /* 7828 */ { MAD_F(0x04be4bb2) /* 0.296458908 */, 19 }, + /* 7829 */ { MAD_F(0x04be80a5) /* 0.296509405 */, 19 }, + /* 7830 */ { MAD_F(0x04beb599) /* 0.296559904 */, 19 }, + /* 7831 */ { MAD_F(0x04beea8d) /* 0.296610404 */, 19 }, + /* 7832 */ { MAD_F(0x04bf1f82) /* 0.296660907 */, 19 }, + /* 7833 */ { MAD_F(0x04bf5477) /* 0.296711413 */, 19 }, + /* 7834 */ { MAD_F(0x04bf896d) /* 0.296761920 */, 19 }, + /* 7835 */ { MAD_F(0x04bfbe64) /* 0.296812429 */, 19 }, + /* 7836 */ { MAD_F(0x04bff35b) /* 0.296862941 */, 19 }, + /* 7837 */ { MAD_F(0x04c02852) /* 0.296913455 */, 19 }, + /* 7838 */ { MAD_F(0x04c05d4b) /* 0.296963971 */, 19 }, + /* 7839 */ { MAD_F(0x04c09243) /* 0.297014489 */, 19 }, + + /* 7840 */ { MAD_F(0x04c0c73d) /* 0.297065009 */, 19 }, + /* 7841 */ { MAD_F(0x04c0fc37) /* 0.297115531 */, 19 }, + /* 7842 */ { MAD_F(0x04c13131) /* 0.297166056 */, 19 }, + /* 7843 */ { MAD_F(0x04c1662d) /* 0.297216582 */, 19 }, + /* 7844 */ { MAD_F(0x04c19b28) /* 0.297267111 */, 19 }, + /* 7845 */ { MAD_F(0x04c1d025) /* 0.297317642 */, 19 }, + /* 7846 */ { MAD_F(0x04c20521) /* 0.297368175 */, 19 }, + /* 7847 */ { MAD_F(0x04c23a1f) /* 0.297418710 */, 19 }, + /* 7848 */ { MAD_F(0x04c26f1d) /* 0.297469248 */, 19 }, + /* 7849 */ { MAD_F(0x04c2a41b) /* 0.297519787 */, 19 }, + /* 7850 */ { MAD_F(0x04c2d91b) /* 0.297570329 */, 19 }, + /* 7851 */ { MAD_F(0x04c30e1a) /* 0.297620873 */, 19 }, + /* 7852 */ { MAD_F(0x04c3431b) /* 0.297671418 */, 19 }, + /* 7853 */ { MAD_F(0x04c3781c) /* 0.297721967 */, 19 }, + /* 7854 */ { MAD_F(0x04c3ad1d) /* 0.297772517 */, 19 }, + /* 7855 */ { MAD_F(0x04c3e21f) /* 0.297823069 */, 19 }, + + /* 7856 */ { MAD_F(0x04c41722) /* 0.297873624 */, 19 }, + /* 7857 */ { MAD_F(0x04c44c25) /* 0.297924180 */, 19 }, + /* 7858 */ { MAD_F(0x04c48129) /* 0.297974739 */, 19 }, + /* 7859 */ { MAD_F(0x04c4b62d) /* 0.298025300 */, 19 }, + /* 7860 */ { MAD_F(0x04c4eb32) /* 0.298075863 */, 19 }, + /* 7861 */ { MAD_F(0x04c52038) /* 0.298126429 */, 19 }, + /* 7862 */ { MAD_F(0x04c5553e) /* 0.298176996 */, 19 }, + /* 7863 */ { MAD_F(0x04c58a44) /* 0.298227565 */, 19 }, + /* 7864 */ { MAD_F(0x04c5bf4c) /* 0.298278137 */, 19 }, + /* 7865 */ { MAD_F(0x04c5f453) /* 0.298328711 */, 19 }, + /* 7866 */ { MAD_F(0x04c6295c) /* 0.298379287 */, 19 }, + /* 7867 */ { MAD_F(0x04c65e65) /* 0.298429865 */, 19 }, + /* 7868 */ { MAD_F(0x04c6936e) /* 0.298480445 */, 19 }, + /* 7869 */ { MAD_F(0x04c6c878) /* 0.298531028 */, 19 }, + /* 7870 */ { MAD_F(0x04c6fd83) /* 0.298581612 */, 19 }, + /* 7871 */ { MAD_F(0x04c7328e) /* 0.298632199 */, 19 }, + + /* 7872 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 19 }, + /* 7873 */ { MAD_F(0x04c79ca7) /* 0.298733379 */, 19 }, + /* 7874 */ { MAD_F(0x04c7d1b4) /* 0.298783972 */, 19 }, + /* 7875 */ { MAD_F(0x04c806c1) /* 0.298834567 */, 19 }, + /* 7876 */ { MAD_F(0x04c83bcf) /* 0.298885165 */, 19 }, + /* 7877 */ { MAD_F(0x04c870de) /* 0.298935764 */, 19 }, + /* 7878 */ { MAD_F(0x04c8a5ed) /* 0.298986366 */, 19 }, + /* 7879 */ { MAD_F(0x04c8dafd) /* 0.299036970 */, 19 }, + /* 7880 */ { MAD_F(0x04c9100d) /* 0.299087576 */, 19 }, + /* 7881 */ { MAD_F(0x04c9451e) /* 0.299138184 */, 19 }, + /* 7882 */ { MAD_F(0x04c97a30) /* 0.299188794 */, 19 }, + /* 7883 */ { MAD_F(0x04c9af42) /* 0.299239406 */, 19 }, + /* 7884 */ { MAD_F(0x04c9e455) /* 0.299290021 */, 19 }, + /* 7885 */ { MAD_F(0x04ca1968) /* 0.299340638 */, 19 }, + /* 7886 */ { MAD_F(0x04ca4e7c) /* 0.299391256 */, 19 }, + /* 7887 */ { MAD_F(0x04ca8391) /* 0.299441877 */, 19 }, + + /* 7888 */ { MAD_F(0x04cab8a6) /* 0.299492500 */, 19 }, + /* 7889 */ { MAD_F(0x04caedbb) /* 0.299543126 */, 19 }, + /* 7890 */ { MAD_F(0x04cb22d1) /* 0.299593753 */, 19 }, + /* 7891 */ { MAD_F(0x04cb57e8) /* 0.299644382 */, 19 }, + /* 7892 */ { MAD_F(0x04cb8d00) /* 0.299695014 */, 19 }, + /* 7893 */ { MAD_F(0x04cbc217) /* 0.299745648 */, 19 }, + /* 7894 */ { MAD_F(0x04cbf730) /* 0.299796284 */, 19 }, + /* 7895 */ { MAD_F(0x04cc2c49) /* 0.299846922 */, 19 }, + /* 7896 */ { MAD_F(0x04cc6163) /* 0.299897562 */, 19 }, + /* 7897 */ { MAD_F(0x04cc967d) /* 0.299948204 */, 19 }, + /* 7898 */ { MAD_F(0x04cccb98) /* 0.299998849 */, 19 }, + /* 7899 */ { MAD_F(0x04cd00b3) /* 0.300049495 */, 19 }, + /* 7900 */ { MAD_F(0x04cd35cf) /* 0.300100144 */, 19 }, + /* 7901 */ { MAD_F(0x04cd6aeb) /* 0.300150795 */, 19 }, + /* 7902 */ { MAD_F(0x04cda008) /* 0.300201448 */, 19 }, + /* 7903 */ { MAD_F(0x04cdd526) /* 0.300252103 */, 19 }, + + /* 7904 */ { MAD_F(0x04ce0a44) /* 0.300302761 */, 19 }, + /* 7905 */ { MAD_F(0x04ce3f63) /* 0.300353420 */, 19 }, + /* 7906 */ { MAD_F(0x04ce7482) /* 0.300404082 */, 19 }, + /* 7907 */ { MAD_F(0x04cea9a2) /* 0.300454745 */, 19 }, + /* 7908 */ { MAD_F(0x04cedec3) /* 0.300505411 */, 19 }, + /* 7909 */ { MAD_F(0x04cf13e4) /* 0.300556079 */, 19 }, + /* 7910 */ { MAD_F(0x04cf4906) /* 0.300606749 */, 19 }, + /* 7911 */ { MAD_F(0x04cf7e28) /* 0.300657421 */, 19 }, + /* 7912 */ { MAD_F(0x04cfb34b) /* 0.300708096 */, 19 }, + /* 7913 */ { MAD_F(0x04cfe86e) /* 0.300758772 */, 19 }, + /* 7914 */ { MAD_F(0x04d01d92) /* 0.300809451 */, 19 }, + /* 7915 */ { MAD_F(0x04d052b6) /* 0.300860132 */, 19 }, + /* 7916 */ { MAD_F(0x04d087db) /* 0.300910815 */, 19 }, + /* 7917 */ { MAD_F(0x04d0bd01) /* 0.300961500 */, 19 }, + /* 7918 */ { MAD_F(0x04d0f227) /* 0.301012187 */, 19 }, + /* 7919 */ { MAD_F(0x04d1274e) /* 0.301062876 */, 19 }, + + /* 7920 */ { MAD_F(0x04d15c76) /* 0.301113568 */, 19 }, + /* 7921 */ { MAD_F(0x04d1919e) /* 0.301164261 */, 19 }, + /* 7922 */ { MAD_F(0x04d1c6c6) /* 0.301214957 */, 19 }, + /* 7923 */ { MAD_F(0x04d1fbef) /* 0.301265655 */, 19 }, + /* 7924 */ { MAD_F(0x04d23119) /* 0.301316355 */, 19 }, + /* 7925 */ { MAD_F(0x04d26643) /* 0.301367057 */, 19 }, + /* 7926 */ { MAD_F(0x04d29b6e) /* 0.301417761 */, 19 }, + /* 7927 */ { MAD_F(0x04d2d099) /* 0.301468468 */, 19 }, + /* 7928 */ { MAD_F(0x04d305c5) /* 0.301519176 */, 19 }, + /* 7929 */ { MAD_F(0x04d33af2) /* 0.301569887 */, 19 }, + /* 7930 */ { MAD_F(0x04d3701f) /* 0.301620599 */, 19 }, + /* 7931 */ { MAD_F(0x04d3a54d) /* 0.301671314 */, 19 }, + /* 7932 */ { MAD_F(0x04d3da7b) /* 0.301722031 */, 19 }, + /* 7933 */ { MAD_F(0x04d40faa) /* 0.301772751 */, 19 }, + /* 7934 */ { MAD_F(0x04d444d9) /* 0.301823472 */, 19 }, + /* 7935 */ { MAD_F(0x04d47a09) /* 0.301874195 */, 19 }, + + /* 7936 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 19 }, + /* 7937 */ { MAD_F(0x04d4e46b) /* 0.301975649 */, 19 }, + /* 7938 */ { MAD_F(0x04d5199c) /* 0.302026378 */, 19 }, + /* 7939 */ { MAD_F(0x04d54ecf) /* 0.302077110 */, 19 }, + /* 7940 */ { MAD_F(0x04d58401) /* 0.302127845 */, 19 }, + /* 7941 */ { MAD_F(0x04d5b935) /* 0.302178581 */, 19 }, + /* 7942 */ { MAD_F(0x04d5ee69) /* 0.302229319 */, 19 }, + /* 7943 */ { MAD_F(0x04d6239d) /* 0.302280060 */, 19 }, + /* 7944 */ { MAD_F(0x04d658d2) /* 0.302330802 */, 19 }, + /* 7945 */ { MAD_F(0x04d68e08) /* 0.302381547 */, 19 }, + /* 7946 */ { MAD_F(0x04d6c33e) /* 0.302432294 */, 19 }, + /* 7947 */ { MAD_F(0x04d6f875) /* 0.302483043 */, 19 }, + /* 7948 */ { MAD_F(0x04d72dad) /* 0.302533794 */, 19 }, + /* 7949 */ { MAD_F(0x04d762e5) /* 0.302584547 */, 19 }, + /* 7950 */ { MAD_F(0x04d7981d) /* 0.302635303 */, 19 }, + /* 7951 */ { MAD_F(0x04d7cd56) /* 0.302686060 */, 19 }, + + /* 7952 */ { MAD_F(0x04d80290) /* 0.302736820 */, 19 }, + /* 7953 */ { MAD_F(0x04d837ca) /* 0.302787581 */, 19 }, + /* 7954 */ { MAD_F(0x04d86d05) /* 0.302838345 */, 19 }, + /* 7955 */ { MAD_F(0x04d8a240) /* 0.302889111 */, 19 }, + /* 7956 */ { MAD_F(0x04d8d77c) /* 0.302939879 */, 19 }, + /* 7957 */ { MAD_F(0x04d90cb9) /* 0.302990650 */, 19 }, + /* 7958 */ { MAD_F(0x04d941f6) /* 0.303041422 */, 19 }, + /* 7959 */ { MAD_F(0x04d97734) /* 0.303092197 */, 19 }, + /* 7960 */ { MAD_F(0x04d9ac72) /* 0.303142973 */, 19 }, + /* 7961 */ { MAD_F(0x04d9e1b1) /* 0.303193752 */, 19 }, + /* 7962 */ { MAD_F(0x04da16f0) /* 0.303244533 */, 19 }, + /* 7963 */ { MAD_F(0x04da4c30) /* 0.303295316 */, 19 }, + /* 7964 */ { MAD_F(0x04da8171) /* 0.303346101 */, 19 }, + /* 7965 */ { MAD_F(0x04dab6b2) /* 0.303396889 */, 19 }, + /* 7966 */ { MAD_F(0x04daebf4) /* 0.303447678 */, 19 }, + /* 7967 */ { MAD_F(0x04db2136) /* 0.303498469 */, 19 }, + + /* 7968 */ { MAD_F(0x04db5679) /* 0.303549263 */, 19 }, + /* 7969 */ { MAD_F(0x04db8bbc) /* 0.303600059 */, 19 }, + /* 7970 */ { MAD_F(0x04dbc100) /* 0.303650857 */, 19 }, + /* 7971 */ { MAD_F(0x04dbf644) /* 0.303701657 */, 19 }, + /* 7972 */ { MAD_F(0x04dc2b8a) /* 0.303752459 */, 19 }, + /* 7973 */ { MAD_F(0x04dc60cf) /* 0.303803263 */, 19 }, + /* 7974 */ { MAD_F(0x04dc9616) /* 0.303854070 */, 19 }, + /* 7975 */ { MAD_F(0x04dccb5c) /* 0.303904878 */, 19 }, + /* 7976 */ { MAD_F(0x04dd00a4) /* 0.303955689 */, 19 }, + /* 7977 */ { MAD_F(0x04dd35ec) /* 0.304006502 */, 19 }, + /* 7978 */ { MAD_F(0x04dd6b34) /* 0.304057317 */, 19 }, + /* 7979 */ { MAD_F(0x04dda07d) /* 0.304108134 */, 19 }, + /* 7980 */ { MAD_F(0x04ddd5c7) /* 0.304158953 */, 19 }, + /* 7981 */ { MAD_F(0x04de0b11) /* 0.304209774 */, 19 }, + /* 7982 */ { MAD_F(0x04de405c) /* 0.304260597 */, 19 }, + /* 7983 */ { MAD_F(0x04de75a7) /* 0.304311423 */, 19 }, + + /* 7984 */ { MAD_F(0x04deaaf3) /* 0.304362251 */, 19 }, + /* 7985 */ { MAD_F(0x04dee040) /* 0.304413080 */, 19 }, + /* 7986 */ { MAD_F(0x04df158d) /* 0.304463912 */, 19 }, + /* 7987 */ { MAD_F(0x04df4adb) /* 0.304514746 */, 19 }, + /* 7988 */ { MAD_F(0x04df8029) /* 0.304565582 */, 19 }, + /* 7989 */ { MAD_F(0x04dfb578) /* 0.304616421 */, 19 }, + /* 7990 */ { MAD_F(0x04dfeac7) /* 0.304667261 */, 19 }, + /* 7991 */ { MAD_F(0x04e02017) /* 0.304718103 */, 19 }, + /* 7992 */ { MAD_F(0x04e05567) /* 0.304768948 */, 19 }, + /* 7993 */ { MAD_F(0x04e08ab8) /* 0.304819795 */, 19 }, + /* 7994 */ { MAD_F(0x04e0c00a) /* 0.304870644 */, 19 }, + /* 7995 */ { MAD_F(0x04e0f55c) /* 0.304921495 */, 19 }, + /* 7996 */ { MAD_F(0x04e12aaf) /* 0.304972348 */, 19 }, + /* 7997 */ { MAD_F(0x04e16002) /* 0.305023203 */, 19 }, + /* 7998 */ { MAD_F(0x04e19556) /* 0.305074060 */, 19 }, + /* 7999 */ { MAD_F(0x04e1caab) /* 0.305124920 */, 19 }, + + /* 8000 */ { MAD_F(0x04e20000) /* 0.305175781 */, 19 }, + /* 8001 */ { MAD_F(0x04e23555) /* 0.305226645 */, 19 }, + /* 8002 */ { MAD_F(0x04e26aac) /* 0.305277511 */, 19 }, + /* 8003 */ { MAD_F(0x04e2a002) /* 0.305328379 */, 19 }, + /* 8004 */ { MAD_F(0x04e2d55a) /* 0.305379249 */, 19 }, + /* 8005 */ { MAD_F(0x04e30ab2) /* 0.305430121 */, 19 }, + /* 8006 */ { MAD_F(0x04e3400a) /* 0.305480995 */, 19 }, + /* 8007 */ { MAD_F(0x04e37563) /* 0.305531872 */, 19 }, + /* 8008 */ { MAD_F(0x04e3aabd) /* 0.305582750 */, 19 }, + /* 8009 */ { MAD_F(0x04e3e017) /* 0.305633631 */, 19 }, + /* 8010 */ { MAD_F(0x04e41572) /* 0.305684513 */, 19 }, + /* 8011 */ { MAD_F(0x04e44acd) /* 0.305735398 */, 19 }, + /* 8012 */ { MAD_F(0x04e48029) /* 0.305786285 */, 19 }, + /* 8013 */ { MAD_F(0x04e4b585) /* 0.305837174 */, 19 }, + /* 8014 */ { MAD_F(0x04e4eae2) /* 0.305888066 */, 19 }, + /* 8015 */ { MAD_F(0x04e52040) /* 0.305938959 */, 19 }, + + /* 8016 */ { MAD_F(0x04e5559e) /* 0.305989854 */, 19 }, + /* 8017 */ { MAD_F(0x04e58afd) /* 0.306040752 */, 19 }, + /* 8018 */ { MAD_F(0x04e5c05c) /* 0.306091652 */, 19 }, + /* 8019 */ { MAD_F(0x04e5f5bc) /* 0.306142554 */, 19 }, + /* 8020 */ { MAD_F(0x04e62b1c) /* 0.306193457 */, 19 }, + /* 8021 */ { MAD_F(0x04e6607d) /* 0.306244364 */, 19 }, + /* 8022 */ { MAD_F(0x04e695df) /* 0.306295272 */, 19 }, + /* 8023 */ { MAD_F(0x04e6cb41) /* 0.306346182 */, 19 }, + /* 8024 */ { MAD_F(0x04e700a3) /* 0.306397094 */, 19 }, + /* 8025 */ { MAD_F(0x04e73607) /* 0.306448009 */, 19 }, + /* 8026 */ { MAD_F(0x04e76b6b) /* 0.306498925 */, 19 }, + /* 8027 */ { MAD_F(0x04e7a0cf) /* 0.306549844 */, 19 }, + /* 8028 */ { MAD_F(0x04e7d634) /* 0.306600765 */, 19 }, + /* 8029 */ { MAD_F(0x04e80b99) /* 0.306651688 */, 19 }, + /* 8030 */ { MAD_F(0x04e84100) /* 0.306702613 */, 19 }, + /* 8031 */ { MAD_F(0x04e87666) /* 0.306753540 */, 19 }, + + /* 8032 */ { MAD_F(0x04e8abcd) /* 0.306804470 */, 19 }, + /* 8033 */ { MAD_F(0x04e8e135) /* 0.306855401 */, 19 }, + /* 8034 */ { MAD_F(0x04e9169e) /* 0.306906334 */, 19 }, + /* 8035 */ { MAD_F(0x04e94c07) /* 0.306957270 */, 19 }, + /* 8036 */ { MAD_F(0x04e98170) /* 0.307008208 */, 19 }, + /* 8037 */ { MAD_F(0x04e9b6da) /* 0.307059148 */, 19 }, + /* 8038 */ { MAD_F(0x04e9ec45) /* 0.307110090 */, 19 }, + /* 8039 */ { MAD_F(0x04ea21b0) /* 0.307161034 */, 19 }, + /* 8040 */ { MAD_F(0x04ea571c) /* 0.307211980 */, 19 }, + /* 8041 */ { MAD_F(0x04ea8c88) /* 0.307262928 */, 19 }, + /* 8042 */ { MAD_F(0x04eac1f5) /* 0.307313879 */, 19 }, + /* 8043 */ { MAD_F(0x04eaf762) /* 0.307364831 */, 19 }, + /* 8044 */ { MAD_F(0x04eb2cd0) /* 0.307415786 */, 19 }, + /* 8045 */ { MAD_F(0x04eb623f) /* 0.307466743 */, 19 }, + /* 8046 */ { MAD_F(0x04eb97ae) /* 0.307517702 */, 19 }, + /* 8047 */ { MAD_F(0x04ebcd1e) /* 0.307568663 */, 19 }, + + /* 8048 */ { MAD_F(0x04ec028e) /* 0.307619626 */, 19 }, + /* 8049 */ { MAD_F(0x04ec37ff) /* 0.307670591 */, 19 }, + /* 8050 */ { MAD_F(0x04ec6d71) /* 0.307721558 */, 19 }, + /* 8051 */ { MAD_F(0x04eca2e3) /* 0.307772528 */, 19 }, + /* 8052 */ { MAD_F(0x04ecd855) /* 0.307823499 */, 19 }, + /* 8053 */ { MAD_F(0x04ed0dc8) /* 0.307874473 */, 19 }, + /* 8054 */ { MAD_F(0x04ed433c) /* 0.307925449 */, 19 }, + /* 8055 */ { MAD_F(0x04ed78b0) /* 0.307976426 */, 19 }, + /* 8056 */ { MAD_F(0x04edae25) /* 0.308027406 */, 19 }, + /* 8057 */ { MAD_F(0x04ede39a) /* 0.308078389 */, 19 }, + /* 8058 */ { MAD_F(0x04ee1910) /* 0.308129373 */, 19 }, + /* 8059 */ { MAD_F(0x04ee4e87) /* 0.308180359 */, 19 }, + /* 8060 */ { MAD_F(0x04ee83fe) /* 0.308231347 */, 19 }, + /* 8061 */ { MAD_F(0x04eeb976) /* 0.308282338 */, 19 }, + /* 8062 */ { MAD_F(0x04eeeeee) /* 0.308333331 */, 19 }, + /* 8063 */ { MAD_F(0x04ef2467) /* 0.308384325 */, 19 }, + + /* 8064 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 19 }, + /* 8065 */ { MAD_F(0x04ef8f5a) /* 0.308486321 */, 19 }, + /* 8066 */ { MAD_F(0x04efc4d5) /* 0.308537322 */, 19 }, + /* 8067 */ { MAD_F(0x04effa50) /* 0.308588325 */, 19 }, + /* 8068 */ { MAD_F(0x04f02fcb) /* 0.308639331 */, 19 }, + /* 8069 */ { MAD_F(0x04f06547) /* 0.308690338 */, 19 }, + /* 8070 */ { MAD_F(0x04f09ac4) /* 0.308741348 */, 19 }, + /* 8071 */ { MAD_F(0x04f0d041) /* 0.308792359 */, 19 }, + /* 8072 */ { MAD_F(0x04f105bf) /* 0.308843373 */, 19 }, + /* 8073 */ { MAD_F(0x04f13b3e) /* 0.308894389 */, 19 }, + /* 8074 */ { MAD_F(0x04f170bd) /* 0.308945407 */, 19 }, + /* 8075 */ { MAD_F(0x04f1a63c) /* 0.308996427 */, 19 }, + /* 8076 */ { MAD_F(0x04f1dbbd) /* 0.309047449 */, 19 }, + /* 8077 */ { MAD_F(0x04f2113d) /* 0.309098473 */, 19 }, + /* 8078 */ { MAD_F(0x04f246bf) /* 0.309149499 */, 19 }, + /* 8079 */ { MAD_F(0x04f27c40) /* 0.309200528 */, 19 }, + + /* 8080 */ { MAD_F(0x04f2b1c3) /* 0.309251558 */, 19 }, + /* 8081 */ { MAD_F(0x04f2e746) /* 0.309302591 */, 19 }, + /* 8082 */ { MAD_F(0x04f31cc9) /* 0.309353626 */, 19 }, + /* 8083 */ { MAD_F(0x04f3524d) /* 0.309404663 */, 19 }, + /* 8084 */ { MAD_F(0x04f387d2) /* 0.309455702 */, 19 }, + /* 8085 */ { MAD_F(0x04f3bd57) /* 0.309506743 */, 19 }, + /* 8086 */ { MAD_F(0x04f3f2dd) /* 0.309557786 */, 19 }, + /* 8087 */ { MAD_F(0x04f42864) /* 0.309608831 */, 19 }, + /* 8088 */ { MAD_F(0x04f45dea) /* 0.309659879 */, 19 }, + /* 8089 */ { MAD_F(0x04f49372) /* 0.309710928 */, 19 }, + /* 8090 */ { MAD_F(0x04f4c8fa) /* 0.309761980 */, 19 }, + /* 8091 */ { MAD_F(0x04f4fe83) /* 0.309813033 */, 19 }, + /* 8092 */ { MAD_F(0x04f5340c) /* 0.309864089 */, 19 }, + /* 8093 */ { MAD_F(0x04f56996) /* 0.309915147 */, 19 }, + /* 8094 */ { MAD_F(0x04f59f20) /* 0.309966207 */, 19 }, + /* 8095 */ { MAD_F(0x04f5d4ab) /* 0.310017269 */, 19 }, + + /* 8096 */ { MAD_F(0x04f60a36) /* 0.310068333 */, 19 }, + /* 8097 */ { MAD_F(0x04f63fc2) /* 0.310119400 */, 19 }, + /* 8098 */ { MAD_F(0x04f6754f) /* 0.310170468 */, 19 }, + /* 8099 */ { MAD_F(0x04f6aadc) /* 0.310221539 */, 19 }, + /* 8100 */ { MAD_F(0x04f6e06a) /* 0.310272611 */, 19 }, + /* 8101 */ { MAD_F(0x04f715f8) /* 0.310323686 */, 19 }, + /* 8102 */ { MAD_F(0x04f74b87) /* 0.310374763 */, 19 }, + /* 8103 */ { MAD_F(0x04f78116) /* 0.310425842 */, 19 }, + /* 8104 */ { MAD_F(0x04f7b6a6) /* 0.310476923 */, 19 }, + /* 8105 */ { MAD_F(0x04f7ec37) /* 0.310528006 */, 19 }, + /* 8106 */ { MAD_F(0x04f821c8) /* 0.310579091 */, 19 }, + /* 8107 */ { MAD_F(0x04f85759) /* 0.310630179 */, 19 }, + /* 8108 */ { MAD_F(0x04f88cec) /* 0.310681268 */, 19 }, + /* 8109 */ { MAD_F(0x04f8c27e) /* 0.310732360 */, 19 }, + /* 8110 */ { MAD_F(0x04f8f812) /* 0.310783453 */, 19 }, + /* 8111 */ { MAD_F(0x04f92da6) /* 0.310834549 */, 19 }, + + /* 8112 */ { MAD_F(0x04f9633a) /* 0.310885647 */, 19 }, + /* 8113 */ { MAD_F(0x04f998cf) /* 0.310936747 */, 19 }, + /* 8114 */ { MAD_F(0x04f9ce65) /* 0.310987849 */, 19 }, + /* 8115 */ { MAD_F(0x04fa03fb) /* 0.311038953 */, 19 }, + /* 8116 */ { MAD_F(0x04fa3992) /* 0.311090059 */, 19 }, + /* 8117 */ { MAD_F(0x04fa6f29) /* 0.311141168 */, 19 }, + /* 8118 */ { MAD_F(0x04faa4c1) /* 0.311192278 */, 19 }, + /* 8119 */ { MAD_F(0x04fada59) /* 0.311243390 */, 19 }, + /* 8120 */ { MAD_F(0x04fb0ff2) /* 0.311294505 */, 19 }, + /* 8121 */ { MAD_F(0x04fb458c) /* 0.311345622 */, 19 }, + /* 8122 */ { MAD_F(0x04fb7b26) /* 0.311396741 */, 19 }, + /* 8123 */ { MAD_F(0x04fbb0c1) /* 0.311447862 */, 19 }, + /* 8124 */ { MAD_F(0x04fbe65c) /* 0.311498985 */, 19 }, + /* 8125 */ { MAD_F(0x04fc1bf8) /* 0.311550110 */, 19 }, + /* 8126 */ { MAD_F(0x04fc5194) /* 0.311601237 */, 19 }, + /* 8127 */ { MAD_F(0x04fc8731) /* 0.311652366 */, 19 }, + + /* 8128 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 19 }, + /* 8129 */ { MAD_F(0x04fcf26c) /* 0.311754631 */, 19 }, + /* 8130 */ { MAD_F(0x04fd280b) /* 0.311805767 */, 19 }, + /* 8131 */ { MAD_F(0x04fd5daa) /* 0.311856905 */, 19 }, + /* 8132 */ { MAD_F(0x04fd934a) /* 0.311908044 */, 19 }, + /* 8133 */ { MAD_F(0x04fdc8ea) /* 0.311959186 */, 19 }, + /* 8134 */ { MAD_F(0x04fdfe8b) /* 0.312010330 */, 19 }, + /* 8135 */ { MAD_F(0x04fe342c) /* 0.312061476 */, 19 }, + /* 8136 */ { MAD_F(0x04fe69ce) /* 0.312112625 */, 19 }, + /* 8137 */ { MAD_F(0x04fe9f71) /* 0.312163775 */, 19 }, + /* 8138 */ { MAD_F(0x04fed514) /* 0.312214927 */, 19 }, + /* 8139 */ { MAD_F(0x04ff0ab8) /* 0.312266082 */, 19 }, + /* 8140 */ { MAD_F(0x04ff405c) /* 0.312317238 */, 19 }, + /* 8141 */ { MAD_F(0x04ff7601) /* 0.312368397 */, 19 }, + /* 8142 */ { MAD_F(0x04ffaba6) /* 0.312419558 */, 19 }, + /* 8143 */ { MAD_F(0x04ffe14c) /* 0.312470720 */, 19 }, + + /* 8144 */ { MAD_F(0x050016f3) /* 0.312521885 */, 19 }, + /* 8145 */ { MAD_F(0x05004c9a) /* 0.312573052 */, 19 }, + /* 8146 */ { MAD_F(0x05008241) /* 0.312624222 */, 19 }, + /* 8147 */ { MAD_F(0x0500b7e9) /* 0.312675393 */, 19 }, + /* 8148 */ { MAD_F(0x0500ed92) /* 0.312726566 */, 19 }, + /* 8149 */ { MAD_F(0x0501233b) /* 0.312777742 */, 19 }, + /* 8150 */ { MAD_F(0x050158e5) /* 0.312828919 */, 19 }, + /* 8151 */ { MAD_F(0x05018e90) /* 0.312880099 */, 19 }, + /* 8152 */ { MAD_F(0x0501c43b) /* 0.312931280 */, 19 }, + /* 8153 */ { MAD_F(0x0501f9e6) /* 0.312982464 */, 19 }, + /* 8154 */ { MAD_F(0x05022f92) /* 0.313033650 */, 19 }, + /* 8155 */ { MAD_F(0x0502653f) /* 0.313084838 */, 19 }, + /* 8156 */ { MAD_F(0x05029aec) /* 0.313136028 */, 19 }, + /* 8157 */ { MAD_F(0x0502d09a) /* 0.313187220 */, 19 }, + /* 8158 */ { MAD_F(0x05030648) /* 0.313238414 */, 19 }, + /* 8159 */ { MAD_F(0x05033bf7) /* 0.313289611 */, 19 }, + + /* 8160 */ { MAD_F(0x050371a7) /* 0.313340809 */, 19 }, + /* 8161 */ { MAD_F(0x0503a757) /* 0.313392010 */, 19 }, + /* 8162 */ { MAD_F(0x0503dd07) /* 0.313443212 */, 19 }, + /* 8163 */ { MAD_F(0x050412b9) /* 0.313494417 */, 19 }, + /* 8164 */ { MAD_F(0x0504486a) /* 0.313545624 */, 19 }, + /* 8165 */ { MAD_F(0x05047e1d) /* 0.313596833 */, 19 }, + /* 8166 */ { MAD_F(0x0504b3cf) /* 0.313648044 */, 19 }, + /* 8167 */ { MAD_F(0x0504e983) /* 0.313699257 */, 19 }, + /* 8168 */ { MAD_F(0x05051f37) /* 0.313750472 */, 19 }, + /* 8169 */ { MAD_F(0x050554eb) /* 0.313801689 */, 19 }, + /* 8170 */ { MAD_F(0x05058aa0) /* 0.313852909 */, 19 }, + /* 8171 */ { MAD_F(0x0505c056) /* 0.313904130 */, 19 }, + /* 8172 */ { MAD_F(0x0505f60c) /* 0.313955354 */, 19 }, + /* 8173 */ { MAD_F(0x05062bc3) /* 0.314006579 */, 19 }, + /* 8174 */ { MAD_F(0x0506617a) /* 0.314057807 */, 19 }, + /* 8175 */ { MAD_F(0x05069732) /* 0.314109037 */, 19 }, + + /* 8176 */ { MAD_F(0x0506cceb) /* 0.314160269 */, 19 }, + /* 8177 */ { MAD_F(0x050702a4) /* 0.314211502 */, 19 }, + /* 8178 */ { MAD_F(0x0507385d) /* 0.314262739 */, 19 }, + /* 8179 */ { MAD_F(0x05076e17) /* 0.314313977 */, 19 }, + /* 8180 */ { MAD_F(0x0507a3d2) /* 0.314365217 */, 19 }, + /* 8181 */ { MAD_F(0x0507d98d) /* 0.314416459 */, 19 }, + /* 8182 */ { MAD_F(0x05080f49) /* 0.314467704 */, 19 }, + /* 8183 */ { MAD_F(0x05084506) /* 0.314518950 */, 19 }, + /* 8184 */ { MAD_F(0x05087ac2) /* 0.314570199 */, 19 }, + /* 8185 */ { MAD_F(0x0508b080) /* 0.314621449 */, 19 }, + /* 8186 */ { MAD_F(0x0508e63e) /* 0.314672702 */, 19 }, + /* 8187 */ { MAD_F(0x05091bfd) /* 0.314723957 */, 19 }, + /* 8188 */ { MAD_F(0x050951bc) /* 0.314775214 */, 19 }, + /* 8189 */ { MAD_F(0x0509877c) /* 0.314826473 */, 19 }, + /* 8190 */ { MAD_F(0x0509bd3c) /* 0.314877734 */, 19 }, + /* 8191 */ { MAD_F(0x0509f2fd) /* 0.314928997 */, 19 }, + + /* 8192 */ { MAD_F(0x050a28be) /* 0.314980262 */, 19 }, + /* 8193 */ { MAD_F(0x050a5e80) /* 0.315031530 */, 19 }, + /* 8194 */ { MAD_F(0x050a9443) /* 0.315082799 */, 19 }, + /* 8195 */ { MAD_F(0x050aca06) /* 0.315134071 */, 19 }, + /* 8196 */ { MAD_F(0x050affc9) /* 0.315185344 */, 19 }, + /* 8197 */ { MAD_F(0x050b358e) /* 0.315236620 */, 19 }, + /* 8198 */ { MAD_F(0x050b6b52) /* 0.315287898 */, 19 }, + /* 8199 */ { MAD_F(0x050ba118) /* 0.315339178 */, 19 }, + /* 8200 */ { MAD_F(0x050bd6de) /* 0.315390460 */, 19 }, + /* 8201 */ { MAD_F(0x050c0ca4) /* 0.315441744 */, 19 }, + /* 8202 */ { MAD_F(0x050c426b) /* 0.315493030 */, 19 }, + /* 8203 */ { MAD_F(0x050c7833) /* 0.315544318 */, 19 }, + /* 8204 */ { MAD_F(0x050cadfb) /* 0.315595608 */, 19 }, + /* 8205 */ { MAD_F(0x050ce3c4) /* 0.315646901 */, 19 }, + /* 8206 */ { MAD_F(0x050d198d) /* 0.315698195 */, 19 } diff --git a/core/multimedia/opieplayer/libmad/sf_table.dat b/core/multimedia/opieplayer/libmad/sf_table.dat new file mode 100644 index 0000000..18e6202 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/sf_table.dat @@ -0,0 +1,100 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +/* + * These are the scalefactor values for Layer I and Layer II. + * The values are from Table B.1 of ISO/IEC 11172-3. + * + * There is some error introduced by the 32-bit fixed-point representation; + * the amount of error is shown. For 16-bit PCM output, this shouldn't be + * too much of a problem. + */ + + MAD_F(0x20000000), /* 2.000000000000 => 2.000000000000, e 0.000000000000 */ + MAD_F(0x1965fea5), /* 1.587401051968 => 1.587401051074, e 0.000000000894 */ + MAD_F(0x1428a2fa), /* 1.259921049895 => 1.259921051562, e -0.000000001667 */ + MAD_F(0x10000000), /* 1.000000000000 => 1.000000000000, e 0.000000000000 */ + MAD_F(0x0cb2ff53), /* 0.793700525984 => 0.793700527400, e -0.000000001416 */ + MAD_F(0x0a14517d), /* 0.629960524947 => 0.629960525781, e -0.000000000833 */ + MAD_F(0x08000000), /* 0.500000000000 => 0.500000000000, e 0.000000000000 */ + MAD_F(0x06597fa9), /* 0.396850262992 => 0.396850261837, e 0.000000001155 */ + + MAD_F(0x050a28be), /* 0.314980262474 => 0.314980261028, e 0.000000001446 */ + MAD_F(0x04000000), /* 0.250000000000 => 0.250000000000, e 0.000000000000 */ + MAD_F(0x032cbfd5), /* 0.198425131496 => 0.198425132781, e -0.000000001285 */ + MAD_F(0x0285145f), /* 0.157490131237 => 0.157490130514, e 0.000000000723 */ + MAD_F(0x02000000), /* 0.125000000000 => 0.125000000000, e 0.000000000000 */ + MAD_F(0x01965fea), /* 0.099212565748 => 0.099212564528, e 0.000000001220 */ + MAD_F(0x01428a30), /* 0.078745065618 => 0.078745067120, e -0.000000001501 */ + MAD_F(0x01000000), /* 0.062500000000 => 0.062500000000, e 0.000000000000 */ + + MAD_F(0x00cb2ff5), /* 0.049606282874 => 0.049606282264, e 0.000000000610 */ + MAD_F(0x00a14518), /* 0.039372532809 => 0.039372533560, e -0.000000000751 */ + MAD_F(0x00800000), /* 0.031250000000 => 0.031250000000, e 0.000000000000 */ + MAD_F(0x006597fb), /* 0.024803141437 => 0.024803142995, e -0.000000001558 */ + MAD_F(0x0050a28c), /* 0.019686266405 => 0.019686266780, e -0.000000000375 */ + MAD_F(0x00400000), /* 0.015625000000 => 0.015625000000, e 0.000000000000 */ + MAD_F(0x0032cbfd), /* 0.012401570719 => 0.012401569635, e 0.000000001084 */ + MAD_F(0x00285146), /* 0.009843133202 => 0.009843133390, e -0.000000000188 */ + + MAD_F(0x00200000), /* 0.007812500000 => 0.007812500000, e 0.000000000000 */ + MAD_F(0x001965ff), /* 0.006200785359 => 0.006200786680, e -0.000000001321 */ + MAD_F(0x001428a3), /* 0.004921566601 => 0.004921566695, e -0.000000000094 */ + MAD_F(0x00100000), /* 0.003906250000 => 0.003906250000, e 0.000000000000 */ + MAD_F(0x000cb2ff), /* 0.003100392680 => 0.003100391477, e 0.000000001202 */ + MAD_F(0x000a1451), /* 0.002460783301 => 0.002460781485, e 0.000000001816 */ + MAD_F(0x00080000), /* 0.001953125000 => 0.001953125000, e 0.000000000000 */ + MAD_F(0x00065980), /* 0.001550196340 => 0.001550197601, e -0.000000001262 */ + + MAD_F(0x00050a29), /* 0.001230391650 => 0.001230392605, e -0.000000000955 */ + MAD_F(0x00040000), /* 0.000976562500 => 0.000976562500, e 0.000000000000 */ + MAD_F(0x00032cc0), /* 0.000775098170 => 0.000775098801, e -0.000000000631 */ + MAD_F(0x00028514), /* 0.000615195825 => 0.000615194440, e 0.000000001385 */ + MAD_F(0x00020000), /* 0.000488281250 => 0.000488281250, e 0.000000000000 */ + MAD_F(0x00019660), /* 0.000387549085 => 0.000387549400, e -0.000000000315 */ + MAD_F(0x0001428a), /* 0.000307597913 => 0.000307597220, e 0.000000000693 */ + MAD_F(0x00010000), /* 0.000244140625 => 0.000244140625, e 0.000000000000 */ + + MAD_F(0x0000cb30), /* 0.000193774542 => 0.000193774700, e -0.000000000158 */ + MAD_F(0x0000a145), /* 0.000153798956 => 0.000153798610, e 0.000000000346 */ + MAD_F(0x00008000), /* 0.000122070313 => 0.000122070313, e 0.000000000000 */ + MAD_F(0x00006598), /* 0.000096887271 => 0.000096887350, e -0.000000000079 */ + MAD_F(0x000050a3), /* 0.000076899478 => 0.000076901168, e -0.000000001689 */ + MAD_F(0x00004000), /* 0.000061035156 => 0.000061035156, e 0.000000000000 */ + MAD_F(0x000032cc), /* 0.000048443636 => 0.000048443675, e -0.000000000039 */ + MAD_F(0x00002851), /* 0.000038449739 => 0.000038448721, e 0.000000001018 */ + + MAD_F(0x00002000), /* 0.000030517578 => 0.000030517578, e 0.000000000000 */ + MAD_F(0x00001966), /* 0.000024221818 => 0.000024221838, e -0.000000000020 */ + MAD_F(0x00001429), /* 0.000019224870 => 0.000019226223, e -0.000000001354 */ + MAD_F(0x00001000), /* 0.000015258789 => 0.000015258789, e -0.000000000000 */ + MAD_F(0x00000cb3), /* 0.000012110909 => 0.000012110919, e -0.000000000010 */ + MAD_F(0x00000a14), /* 0.000009612435 => 0.000009611249, e 0.000000001186 */ + MAD_F(0x00000800), /* 0.000007629395 => 0.000007629395, e -0.000000000000 */ + MAD_F(0x00000659), /* 0.000006055454 => 0.000006053597, e 0.000000001858 */ + + MAD_F(0x0000050a), /* 0.000004806217 => 0.000004805624, e 0.000000000593 */ + MAD_F(0x00000400), /* 0.000003814697 => 0.000003814697, e 0.000000000000 */ + MAD_F(0x0000032d), /* 0.000003027727 => 0.000003028661, e -0.000000000934 */ + MAD_F(0x00000285), /* 0.000002403109 => 0.000002402812, e 0.000000000296 */ + MAD_F(0x00000200), /* 0.000001907349 => 0.000001907349, e -0.000000000000 */ + MAD_F(0x00000196), /* 0.000001513864 => 0.000001512468, e 0.000000001396 */ + MAD_F(0x00000143) /* 0.000001201554 => 0.000001203269, e -0.000000001714 */ diff --git a/core/multimedia/opieplayer/libmad/stream.c b/core/multimedia/opieplayer/libmad/stream.c new file mode 100644 index 0000000..dea7b8e --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/stream.c @@ -0,0 +1,123 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifdef HAVE_CONFIG_H +# include "libmad_config.h" +# endif + +# include "libmad_global.h" + +# include + +# include "bit.h" +# include "stream.h" + +/* + * NAME: stream->init() + * DESCRIPTION: initialize stream struct + */ +void mad_stream_init(struct mad_stream *stream) +{ + stream->buffer = 0; + stream->bufend = 0; + stream->skiplen = 0; + + stream->sync = 0; + stream->freerate = 0; + + stream->this_frame = 0; + stream->next_frame = 0; + mad_bit_init(&stream->ptr, 0); + + mad_bit_init(&stream->anc_ptr, 0); + stream->anc_bitlen = 0; + + stream->main_data = 0; + stream->md_len = 0; + + stream->options = 0; + stream->error = 0; +} + +/* + * NAME: stream->finish() + * DESCRIPTION: deallocate any dynamic memory associated with stream + */ +void mad_stream_finish(struct mad_stream *stream) +{ + if (stream->main_data) { + free(stream->main_data); + stream->main_data = 0; + } + + mad_bit_finish(&stream->anc_ptr); + mad_bit_finish(&stream->ptr); +} + +/* + * NAME: stream->buffer() + * DESCRIPTION: set stream buffer pointers + */ +void mad_stream_buffer(struct mad_stream *stream, + unsigned char const *buffer, unsigned long length) +{ + stream->buffer = buffer; + stream->bufend = buffer + length; + + stream->this_frame = buffer; + stream->next_frame = buffer; + + stream->sync = 1; + + mad_bit_init(&stream->ptr, buffer); +} + +/* + * NAME: stream->skip() + * DESCRIPTION: arrange to skip bytes before the next frame + */ +void mad_stream_skip(struct mad_stream *stream, unsigned long length) +{ + stream->skiplen += length; +} + +/* + * NAME: stream->sync() + * DESCRIPTION: locate the next stream sync word + */ +int mad_stream_sync(struct mad_stream *stream) +{ + register unsigned char const *ptr, *end; + + ptr = mad_bit_nextbyte(&stream->ptr); + end = stream->bufend; + + while (ptr < end - 1 && + !(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) + ++ptr; + + if (end - ptr < MAD_BUFFER_GUARD) + return -1; + + mad_bit_init(&stream->ptr, ptr); + + return 0; +} diff --git a/core/multimedia/opieplayer/libmad/stream.h b/core/multimedia/opieplayer/libmad/stream.h new file mode 100644 index 0000000..cf3280e --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/stream.h @@ -0,0 +1,102 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_STREAM_H +# define LIBMAD_STREAM_H + +# include "bit.h" + +# define MAD_BUFFER_GUARD 8 +# define MAD_BUFFER_MDLEN (511 + 2048 + MAD_BUFFER_GUARD) + +enum mad_error { + MAD_ERROR_BUFLEN = 0x0001, /* input buffer too small (or EOF) */ + MAD_ERROR_BUFPTR = 0x0002, /* invalid (null) buffer pointer */ + + MAD_ERROR_NOMEM = 0x0031, /* not enough memory */ + + MAD_ERROR_LOSTSYNC = 0x0101, /* lost synchronization */ + MAD_ERROR_BADLAYER = 0x0102, /* reserved header layer value */ + MAD_ERROR_BADBITRATE = 0x0103, /* forbidden bitrate value */ + MAD_ERROR_BADSAMPLERATE = 0x0104, /* reserved sample frequency value */ + MAD_ERROR_BADEMPHASIS = 0x0105, /* reserved emphasis value */ + + MAD_ERROR_BADCRC = 0x0201, /* CRC check failed */ + MAD_ERROR_BADBITALLOC = 0x0211, /* forbidden bit allocation value */ + MAD_ERROR_BADSCALEFACTOR = 0x0221, /* bad scalefactor index */ + MAD_ERROR_BADFRAMELEN = 0x0231, /* bad frame length */ + MAD_ERROR_BADBIGVALUES = 0x0232, /* bad big_values count */ + MAD_ERROR_BADBLOCKTYPE = 0x0233, /* reserved block_type */ + MAD_ERROR_BADSCFSI = 0x0234, /* bad scalefactor selection info */ + MAD_ERROR_BADDATAPTR = 0x0235, /* bad main_data_begin pointer */ + MAD_ERROR_BADPART3LEN = 0x0236, /* bad audio data length */ + MAD_ERROR_BADHUFFTABLE = 0x0237, /* bad Huffman table select */ + MAD_ERROR_BADHUFFDATA = 0x0238, /* Huffman data overrun */ + MAD_ERROR_BADSTEREO = 0x0239 /* incompatible block_type for JS */ +}; + +# define MAD_RECOVERABLE(error) ((error) & 0xff00) + +struct mad_stream { + unsigned char const *buffer; /* input bitstream buffer */ + unsigned char const *bufend; /* end of buffer */ + unsigned long skiplen; /* bytes to skip before next frame */ + + int sync; /* stream sync found */ + unsigned long freerate; /* free bitrate (fixed) */ + + unsigned char const *this_frame; /* start of current frame */ + unsigned char const *next_frame; /* start of next frame */ + struct mad_bitptr ptr; /* current processing bit pointer */ + + struct mad_bitptr anc_ptr; /* ancillary bits pointer */ + unsigned int anc_bitlen; /* number of ancillary bits */ + + unsigned char (*main_data)[MAD_BUFFER_MDLEN]; + /* Layer III main_data() */ + unsigned int md_len; /* bytes in main_data */ + + int options; /* decoding options (see below) */ + enum mad_error error; /* error code (see above) */ +}; + +enum { + MAD_OPTION_IGNORECRC = 0x0001, /* ignore CRC errors */ + MAD_OPTION_HALFSAMPLERATE = 0x0002, /* generate PCM at 1/2 sample rate */ +# if 0 /* not yet implemented */ + MAD_OPTION_LEFTCHANNEL = 0x0010, /* decode left channel only */ + MAD_OPTION_RIGHTCHANNEL = 0x0020, /* decode right channel only */ + MAD_OPTION_SINGLECHANNEL = 0x0030, /* combine channels */ +# endif +}; + +void mad_stream_init(struct mad_stream *); +void mad_stream_finish(struct mad_stream *); + +# define mad_stream_options(stream, opts) ((stream)->options = (opts)) + +void mad_stream_buffer(struct mad_stream *, + unsigned char const *, unsigned long); +void mad_stream_skip(struct mad_stream *, unsigned long); + +int mad_stream_sync(struct mad_stream *); + +# endif diff --git a/core/multimedia/opieplayer/libmad/synth.c b/core/multimedia/opieplayer/libmad/synth.c new file mode 100644 index 0000000..e1914c9 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/synth.c @@ -0,0 +1,855 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifdef HAVE_CONFIG_H +# include "libmad_config.h" +# endif + +# include "libmad_global.h" + +# include "fixed.h" +# include "frame.h" +# include "synth.h" + +/* + * NAME: synth->init() + * DESCRIPTION: initialize synth struct + */ +void mad_synth_init(struct mad_synth *synth) +{ + mad_synth_mute(synth); + + synth->phase = 0; + + synth->pcm.samplerate = 0; + synth->pcm.channels = 0; + synth->pcm.length = 0; +} + +/* + * NAME: synth->mute() + * DESCRIPTION: zero all polyphase filterbank values, resetting synthesis + */ +void mad_synth_mute(struct mad_synth *synth) +{ + unsigned int ch, s, v; + + for (ch = 0; ch < 2; ++ch) { + for (s = 0; s < 16; ++s) { + for (v = 0; v < 8; ++v) { + synth->filter[ch][0][0][s][v] = synth->filter[ch][0][1][s][v] = + synth->filter[ch][1][0][s][v] = synth->filter[ch][1][1][s][v] = 0; + } + } + } +} + +/* + * An optional optimization called here the Subband Synthesis Optimization + * (SSO) improves the performance of subband synthesis at the expense of + * accuracy. + * + * The idea is to simplify 32x32->64-bit multiplication to 32x32->32 such + * that extra scaling and rounding are not necessary. This often allows the + * compiler to use faster 32-bit multiply-accumulate instructions instead of + * explicit 64-bit multiply, shift, and add instructions. + * + * SSO works like this: a full 32x32->64-bit multiply of two mad_fixed_t + * values requires the result to be right-shifted 28 bits to be properly + * scaled to the same fixed-point format. Right shifts can be applied at any + * time to either operand or to the result, so the optimization involves + * careful placement of these shifts to minimize the loss of accuracy. + * + * First, a 14-bit shift is applied with rounding at compile-time to the D[] + * table of coefficients for the subband synthesis window. This only loses 2 + * bits of accuracy because the lower 12 bits are always zero. A second + * 12-bit shift occurs after the DCT calculation. This loses 12 bits of + * accuracy. Finally, a third 2-bit shift occurs just before the sample is + * saved in the PCM buffer. 14 + 12 + 2 == 28 bits. + */ + +/* FPM_DEFAULT without OPT_SSO will actually lose accuracy and performance */ + +# if defined(FPM_DEFAULT) && !defined(OPT_SSO) +# define OPT_SSO +# endif + +/* second SSO shift, with rounding */ + +# if defined(OPT_SSO) +# define SHIFT(x) (((x) + (1L << 11)) >> 12) +# else +# define SHIFT(x) (x) +# endif + +/* possible DCT speed optimization */ + +# if defined(OPT_SPEED) && defined(MAD_F_MLX) +# define OPT_DCTO +# define MUL(x, y) \ + ({ mad_fixed64hi_t hi; \ + mad_fixed64lo_t lo; \ + MAD_F_MLX(hi, lo, (x), (y)); \ + hi << (32 - MAD_F_SCALEBITS - 3); \ + }) +# else +# undef OPT_DCTO +# define MUL(x, y) mad_f_mul((x), (y)) +# endif + +/* + * NAME: dct32() + * DESCRIPTION: perform fast in[32]->out[32] DCT + */ +static +void dct32(mad_fixed_t const in[32], unsigned int slot, + mad_fixed_t lo[16][8], mad_fixed_t hi[16][8]) +{ + mad_fixed_t t0, t1, t2, t3, t4, t5, t6, t7; + mad_fixed_t t8, t9, t10, t11, t12, t13, t14, t15; + mad_fixed_t t16, t17, t18, t19, t20, t21, t22, t23; + mad_fixed_t t24, t25, t26, t27, t28, t29, t30, t31; + mad_fixed_t t32, t33, t34, t35, t36, t37, t38, t39; + mad_fixed_t t40, t41, t42, t43, t44, t45, t46, t47; + mad_fixed_t t48, t49, t50, t51, t52, t53, t54, t55; + mad_fixed_t t56, t57, t58, t59, t60, t61, t62, t63; + mad_fixed_t t64, t65, t66, t67, t68, t69, t70, t71; + mad_fixed_t t72, t73, t74, t75, t76, t77, t78, t79; + mad_fixed_t t80, t81, t82, t83, t84, t85, t86, t87; + mad_fixed_t t88, t89, t90, t91, t92, t93, t94, t95; + mad_fixed_t t96, t97, t98, t99, t100, t101, t102, t103; + mad_fixed_t t104, t105, t106, t107, t108, t109, t110, t111; + mad_fixed_t t112, t113, t114, t115, t116, t117, t118, t119; + mad_fixed_t t120, t121, t122, t123, t124, t125, t126, t127; + mad_fixed_t t128, t129, t130, t131, t132, t133, t134, t135; + mad_fixed_t t136, t137, t138, t139, t140, t141, t142, t143; + mad_fixed_t t144, t145, t146, t147, t148, t149, t150, t151; + mad_fixed_t t152, t153, t154, t155, t156, t157, t158, t159; + mad_fixed_t t160, t161, t162, t163, t164, t165, t166, t167; + mad_fixed_t t168, t169, t170, t171, t172, t173, t174, t175; + mad_fixed_t t176; + + /* costab[i] = cos(PI / (2 * 32) * i) */ + +# if defined(OPT_DCTO) + enum { + costab1 = MAD_F(0x7fd8878e), + costab2 = MAD_F(0x7f62368f), + costab3 = MAD_F(0x7e9d55fc), + costab4 = MAD_F(0x7d8a5f40), + costab5 = MAD_F(0x7c29fbee), + costab6 = MAD_F(0x7a7d055b), + costab7 = MAD_F(0x78848414), + costab8 = MAD_F(0x7641af3d), + costab9 = MAD_F(0x73b5ebd1), + costab10 = MAD_F(0x70e2cbc6), + costab11 = MAD_F(0x6dca0d14), + costab12 = MAD_F(0x6a6d98a4), + costab13 = MAD_F(0x66cf8120), + costab14 = MAD_F(0x62f201ac), + costab15 = MAD_F(0x5ed77c8a), + costab16 = MAD_F(0x5a82799a), + costab17 = MAD_F(0x55f5a4d2), + costab18 = MAD_F(0x5133cc94), + costab19 = MAD_F(0x4c3fdff4), + costab20 = MAD_F(0x471cece7), + costab21 = MAD_F(0x41ce1e65), + costab22 = MAD_F(0x3c56ba70), + costab23 = MAD_F(0x36ba2014), + costab24 = MAD_F(0x30fbc54d), + costab25 = MAD_F(0x2b1f34eb), + costab26 = MAD_F(0x25280c5e), + costab27 = MAD_F(0x1f19f97b), + costab28 = MAD_F(0x18f8b83c), + costab29 = MAD_F(0x12c8106f), + costab30 = MAD_F(0x0c8bd35e), + costab31 = MAD_F(0x0647d97c) + }; +# else + enum { + costab1 = MAD_F(0x0ffb10f2), /* 0.998795456 */ + costab2 = MAD_F(0x0fec46d2), /* 0.995184727 */ + costab3 = MAD_F(0x0fd3aac0), /* 0.989176510 */ + costab4 = MAD_F(0x0fb14be8), /* 0.980785280 */ + costab5 = MAD_F(0x0f853f7e), /* 0.970031253 */ + costab6 = MAD_F(0x0f4fa0ab), /* 0.956940336 */ + costab7 = MAD_F(0x0f109082), /* 0.941544065 */ + costab8 = MAD_F(0x0ec835e8), /* 0.923879533 */ + costab9 = MAD_F(0x0e76bd7a), /* 0.903989293 */ + costab10 = MAD_F(0x0e1c5979), /* 0.881921264 */ + costab11 = MAD_F(0x0db941a3), /* 0.857728610 */ + costab12 = MAD_F(0x0d4db315), /* 0.831469612 */ + costab13 = MAD_F(0x0cd9f024), /* 0.803207531 */ + costab14 = MAD_F(0x0c5e4036), /* 0.773010453 */ + costab15 = MAD_F(0x0bdaef91), /* 0.740951125 */ + costab16 = MAD_F(0x0b504f33), /* 0.707106781 */ + costab17 = MAD_F(0x0abeb49a), /* 0.671558955 */ + costab18 = MAD_F(0x0a267993), /* 0.634393284 */ + costab19 = MAD_F(0x0987fbfe), /* 0.595699304 */ + costab20 = MAD_F(0x08e39d9d), /* 0.555570233 */ + costab21 = MAD_F(0x0839c3cd), /* 0.514102744 */ + costab22 = MAD_F(0x078ad74e), /* 0.471396737 */ + costab23 = MAD_F(0x06d74402), /* 0.427555093 */ + costab24 = MAD_F(0x061f78aa), /* 0.382683432 */ + costab25 = MAD_F(0x0563e69d), /* 0.336889853 */ + costab26 = MAD_F(0x04a5018c), /* 0.290284677 */ + costab27 = MAD_F(0x03e33f2f), /* 0.242980180 */ + costab28 = MAD_F(0x031f1708), /* 0.195090322 */ + costab29 = MAD_F(0x0259020e), /* 0.146730474 */ + costab30 = MAD_F(0x01917a6c), /* 0.098017140 */ + costab31 = MAD_F(0x00c8fb30) /* 0.049067674 */ + }; +# endif + + t0 = in[0] + in[31]; t16 = MUL(in[0] - in[31], costab1); + t1 = in[15] + in[16]; t17 = MUL(in[15] - in[16], costab31); + + t41 = t16 + t17; + t59 = MUL(t16 - t17, costab2); + t33 = t0 + t1; + t50 = MUL(t0 - t1, costab2); + + t2 = in[7] + in[24]; t18 = MUL(in[7] - in[24], costab15); + t3 = in[8] + in[23]; t19 = MUL(in[8] - in[23], costab17); + + t42 = t18 + t19; + t60 = MUL(t18 - t19, costab30); + t34 = t2 + t3; + t51 = MUL(t2 - t3, costab30); + + t4 = in[3] + in[28]; t20 = MUL(in[3] - in[28], costab7); + t5 = in[12] + in[19]; t21 = MUL(in[12] - in[19], costab25); + + t43 = t20 + t21; + t61 = MUL(t20 - t21, costab14); + t35 = t4 + t5; + t52 = MUL(t4 - t5, costab14); + + t6 = in[4] + in[27]; t22 = MUL(in[4] - in[27], costab9); + t7 = in[11] + in[20]; t23 = MUL(in[11] - in[20], costab23); + + t44 = t22 + t23; + t62 = MUL(t22 - t23, costab18); + t36 = t6 + t7; + t53 = MUL(t6 - t7, costab18); + + t8 = in[1] + in[30]; t24 = MUL(in[1] - in[30], costab3); + t9 = in[14] + in[17]; t25 = MUL(in[14] - in[17], costab29); + + t45 = t24 + t25; + t63 = MUL(t24 - t25, costab6); + t37 = t8 + t9; + t54 = MUL(t8 - t9, costab6); + + t10 = in[6] + in[25]; t26 = MUL(in[6] - in[25], costab13); + t11 = in[9] + in[22]; t27 = MUL(in[9] - in[22], costab19); + + t46 = t26 + t27; + t64 = MUL(t26 - t27, costab26); + t38 = t10 + t11; + t55 = MUL(t10 - t11, costab26); + + t12 = in[2] + in[29]; t28 = MUL(in[2] - in[29], costab5); + t13 = in[13] + in[18]; t29 = MUL(in[13] - in[18], costab27); + + t47 = t28 + t29; + t65 = MUL(t28 - t29, costab10); + t39 = t12 + t13; + t56 = MUL(t12 - t13, costab10); + + t14 = in[5] + in[26]; t30 = MUL(in[5] - in[26], costab11); + t15 = in[10] + in[21]; t31 = MUL(in[10] - in[21], costab21); + + t48 = t30 + t31; + t66 = MUL(t30 - t31, costab22); + t40 = t14 + t15; + t57 = MUL(t14 - t15, costab22); + + t69 = t33 + t34; t89 = MUL(t33 - t34, costab4); + t70 = t35 + t36; t90 = MUL(t35 - t36, costab28); + t71 = t37 + t38; t91 = MUL(t37 - t38, costab12); + t72 = t39 + t40; t92 = MUL(t39 - t40, costab20); + t73 = t41 + t42; t94 = MUL(t41 - t42, costab4); + t74 = t43 + t44; t95 = MUL(t43 - t44, costab28); + t75 = t45 + t46; t96 = MUL(t45 - t46, costab12); + t76 = t47 + t48; t97 = MUL(t47 - t48, costab20); + + t78 = t50 + t51; t100 = MUL(t50 - t51, costab4); + t79 = t52 + t53; t101 = MUL(t52 - t53, costab28); + t80 = t54 + t55; t102 = MUL(t54 - t55, costab12); + t81 = t56 + t57; t103 = MUL(t56 - t57, costab20); + + t83 = t59 + t60; t106 = MUL(t59 - t60, costab4); + t84 = t61 + t62; t107 = MUL(t61 - t62, costab28); + t85 = t63 + t64; t108 = MUL(t63 - t64, costab12); + t86 = t65 + t66; t109 = MUL(t65 - t66, costab20); + + t113 = t69 + t70; + t114 = t71 + t72; + + /* 0 */ hi[15][slot] = SHIFT(t113 + t114); + /* 16 */ lo[ 0][slot] = SHIFT(MUL(t113 - t114, costab16)); + + t115 = t73 + t74; + t116 = t75 + t76; + + t32 = t115 + t116; + + /* 1 */ hi[14][slot] = SHIFT(t32); + + t118 = t78 + t79; + t119 = t80 + t81; + + t58 = t118 + t119; + + /* 2 */ hi[13][slot] = SHIFT(t58); + + t121 = t83 + t84; + t122 = t85 + t86; + + t67 = t121 + t122; + + t49 = (t67 << 1) - t32; + + /* 3 */ hi[12][slot] = SHIFT(t49); + + t125 = t89 + t90; + t126 = t91 + t92; + + t93 = t125 + t126; + + /* 4 */ hi[11][slot] = SHIFT(t93); + + t128 = t94 + t95; + t129 = t96 + t97; + + t98 = t128 + t129; + + t68 = (t98 << 1) - t49; + + /* 5 */ hi[10][slot] = SHIFT(t68); + + t132 = t100 + t101; + t133 = t102 + t103; + + t104 = t132 + t133; + + t82 = (t104 << 1) - t58; + + /* 6 */ hi[ 9][slot] = SHIFT(t82); + + t136 = t106 + t107; + t137 = t108 + t109; + + t110 = t136 + t137; + + t87 = (t110 << 1) - t67; + + t77 = (t87 << 1) - t68; + + /* 7 */ hi[ 8][slot] = SHIFT(t77); + + t141 = MUL(t69 - t70, costab8); + t142 = MUL(t71 - t72, costab24); + t143 = t141 + t142; + + /* 8 */ hi[ 7][slot] = SHIFT(t143); + /* 24 */ lo[ 8][slot] = + SHIFT((MUL(t141 - t142, costab16) << 1) - t143); + + t144 = MUL(t73 - t74, costab8); + t145 = MUL(t75 - t76, costab24); + t146 = t144 + t145; + + t88 = (t146 << 1) - t77; + + /* 9 */ hi[ 6][slot] = SHIFT(t88); + + t148 = MUL(t78 - t79, costab8); + t149 = MUL(t80 - t81, costab24); + t150 = t148 + t149; + + t105 = (t150 << 1) - t82; + + /* 10 */ hi[ 5][slot] = SHIFT(t105); + + t152 = MUL(t83 - t84, costab8); + t153 = MUL(t85 - t86, costab24); + t154 = t152 + t153; + + t111 = (t154 << 1) - t87; + + t99 = (t111 << 1) - t88; + + /* 11 */ hi[ 4][slot] = SHIFT(t99); + + t157 = MUL(t89 - t90, costab8); + t158 = MUL(t91 - t92, costab24); + t159 = t157 + t158; + + t127 = (t159 << 1) - t93; + + /* 12 */ hi[ 3][slot] = SHIFT(t127); + + t160 = (MUL(t125 - t126, costab16) << 1) - t127; + + /* 20 */ lo[ 4][slot] = SHIFT(t160); + /* 28 */ lo[12][slot] = + SHIFT((((MUL(t157 - t158, costab16) << 1) - t159) << 1) - t160); + + t161 = MUL(t94 - t95, costab8); + t162 = MUL(t96 - t97, costab24); + t163 = t161 + t162; + + t130 = (t163 << 1) - t98; + + t112 = (t130 << 1) - t99; + + /* 13 */ hi[ 2][slot] = SHIFT(t112); + + t164 = (MUL(t128 - t129, costab16) << 1) - t130; + + t166 = MUL(t100 - t101, costab8); + t167 = MUL(t102 - t103, costab24); + t168 = t166 + t167; + + t134 = (t168 << 1) - t104; + + t120 = (t134 << 1) - t105; + + /* 14 */ hi[ 1][slot] = SHIFT(t120); + + t135 = (MUL(t118 - t119, costab16) << 1) - t120; + + /* 18 */ lo[ 2][slot] = SHIFT(t135); + + t169 = (MUL(t132 - t133, costab16) << 1) - t134; + + t151 = (t169 << 1) - t135; + + /* 22 */ lo[ 6][slot] = SHIFT(t151); + + t170 = (((MUL(t148 - t149, costab16) << 1) - t150) << 1) - t151; + + /* 26 */ lo[10][slot] = SHIFT(t170); + /* 30 */ lo[14][slot] = + SHIFT((((((MUL(t166 - t167, costab16) << 1) - + t168) << 1) - t169) << 1) - t170); + + t171 = MUL(t106 - t107, costab8); + t172 = MUL(t108 - t109, costab24); + t173 = t171 + t172; + + t138 = (t173 << 1) - t110; + + t123 = (t138 << 1) - t111; + + t139 = (MUL(t121 - t122, costab16) << 1) - t123; + + t117 = (t123 << 1) - t112; + + /* 15 */ hi[ 0][slot] = SHIFT(t117); + + t124 = (MUL(t115 - t116, costab16) << 1) - t117; + + /* 17 */ lo[ 1][slot] = SHIFT(t124); + + t131 = (t139 << 1) - t124; + + /* 19 */ lo[ 3][slot] = SHIFT(t131); + + t140 = (t164 << 1) - t131; + + /* 21 */ lo[ 5][slot] = SHIFT(t140); + + t174 = (MUL(t136 - t137, costab16) << 1) - t138; + + t155 = (t174 << 1) - t139; + + t147 = (t155 << 1) - t140; + + /* 23 */ lo[ 7][slot] = SHIFT(t147); + + t156 = (((MUL(t144 - t145, costab16) << 1) - t146) << 1) - t147; + + /* 25 */ lo[ 9][slot] = SHIFT(t156); + + t175 = (((MUL(t152 - t153, costab16) << 1) - t154) << 1) - t155; + + t165 = (t175 << 1) - t156; + + /* 27 */ lo[11][slot] = SHIFT(t165); + + t176 = (((((MUL(t161 - t162, costab16) << 1) - + t163) << 1) - t164) << 1) - t165; + + /* 29 */ lo[13][slot] = SHIFT(t176); + /* 31 */ lo[15][slot] = + SHIFT((((((((MUL(t171 - t172, costab16) << 1) - + t173) << 1) - t174) << 1) - t175) << 1) - t176); + + /* + * Totals: + * 80 multiplies + * 80 additions + * 119 subtractions + * 49 shifts (not counting SSO) + */ +} + +# undef MUL +# undef SHIFT + +/* third SSO shift and/or D[] optimization preshift */ + +# if defined(OPT_SSO) +# if MAD_F_FRACBITS != 28 +# error "MAD_F_FRACBITS must be 28 to use OPT_SSO" +# endif +# define ML0(hi, lo, x, y) ((lo) = (x) * (y)) +# define MLA(hi, lo, x, y) ((lo) += (x) * (y)) +# define MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) +# define SHIFT(x) ((x) >> 2) +# define PRESHIFT(x) ((MAD_F(x) + (1L << 13)) >> 14) +# else +# define ML0(hi, lo, x, y) MAD_F_ML0((hi), (lo), (x), (y)) +# define MLA(hi, lo, x, y) MAD_F_MLA((hi), (lo), (x), (y)) +# define MLZ(hi, lo) MAD_F_MLZ((hi), (lo)) +# define SHIFT(x) (x) +# if defined(MAD_F_SCALEBITS) +# undef MAD_F_SCALEBITS +# define MAD_F_SCALEBITS (MAD_F_FRACBITS - 12) +# define PRESHIFT(x) (MAD_F(x) >> 12) +# else +# define PRESHIFT(x) MAD_F(x) +# endif +# endif + +static +mad_fixed_t const D[17][32] = { +# include "D.dat" +}; + +# if defined(ASO_SYNTH) +void synth_full(struct mad_synth *, struct mad_frame const *, + unsigned int, unsigned int); +# else +/* + * NAME: synth->full() + * DESCRIPTION: perform full frequency PCM synthesis + */ +static +void synth_full(struct mad_synth *synth, struct mad_frame const *frame, + unsigned int nch, unsigned int ns) +{ + unsigned int phase, ch, s, sb, pe, po; + mad_fixed_t *pcm1, *pcm2, (*filter)[2][2][16][8]; + mad_fixed_t const (*sbsample)[36][32]; + register mad_fixed_t (*fe)[8], (*fx)[8], (*fo)[8]; + register mad_fixed_t const (*Dptr)[32], *ptr; + register mad_fixed64hi_t hi; + register mad_fixed64lo_t lo; + + for (ch = 0; ch < nch; ++ch) { + sbsample = &frame->sbsample[ch]; + filter = &synth->filter[ch]; + phase = synth->phase; + pcm1 = synth->pcm.samples[ch]; + + for (s = 0; s < ns; ++s) { + dct32((*sbsample)[s], phase >> 1, + (*filter)[0][phase & 1], (*filter)[1][phase & 1]); + + pe = phase & ~1; + po = ((phase - 1) & 0xf) | 1; + + /* calculate 32 samples */ + + fe = &(*filter)[0][ phase & 1][0]; + fx = &(*filter)[0][~phase & 1][0]; + fo = &(*filter)[1][~phase & 1][0]; + + Dptr = &D[0]; + + ptr = *Dptr + pe; + ML0(hi, lo, (*fe)[0], ptr[ 0]); + MLA(hi, lo, (*fe)[1], ptr[14]); + MLA(hi, lo, (*fe)[2], ptr[12]); + MLA(hi, lo, (*fe)[3], ptr[10]); + MLA(hi, lo, (*fe)[4], ptr[ 8]); + MLA(hi, lo, (*fe)[5], ptr[ 6]); + MLA(hi, lo, (*fe)[6], ptr[ 4]); + MLA(hi, lo, (*fe)[7], ptr[ 2]); + + ptr = *Dptr + po; + MLA(hi, lo, (*fx)[0], -ptr[ 0]); + MLA(hi, lo, (*fx)[1], -ptr[14]); + MLA(hi, lo, (*fx)[2], -ptr[12]); + MLA(hi, lo, (*fx)[3], -ptr[10]); + MLA(hi, lo, (*fx)[4], -ptr[ 8]); + MLA(hi, lo, (*fx)[5], -ptr[ 6]); + MLA(hi, lo, (*fx)[6], -ptr[ 4]); + MLA(hi, lo, (*fx)[7], -ptr[ 2]); + + *pcm1++ = SHIFT(MLZ(hi, lo)); + + pcm2 = pcm1 + 30; + + for (sb = 1; sb < 16; ++sb) { + ++fe; + ++Dptr; + + /* D[32 - sb][i] == -D[sb][31 - i] */ + + ptr = *Dptr + pe; + ML0(hi, lo, (*fe)[7], ptr[ 2]); + MLA(hi, lo, (*fe)[6], ptr[ 4]); + MLA(hi, lo, (*fe)[5], ptr[ 6]); + MLA(hi, lo, (*fe)[4], ptr[ 8]); + MLA(hi, lo, (*fe)[3], ptr[10]); + MLA(hi, lo, (*fe)[2], ptr[12]); + MLA(hi, lo, (*fe)[1], ptr[14]); + MLA(hi, lo, (*fe)[0], ptr[ 0]); + + ptr = *Dptr + po; + MLA(hi, lo, (*fo)[0], -ptr[ 0]); + MLA(hi, lo, (*fo)[1], -ptr[14]); + MLA(hi, lo, (*fo)[2], -ptr[12]); + MLA(hi, lo, (*fo)[3], -ptr[10]); + MLA(hi, lo, (*fo)[4], -ptr[ 8]); + MLA(hi, lo, (*fo)[5], -ptr[ 6]); + MLA(hi, lo, (*fo)[6], -ptr[ 4]); + MLA(hi, lo, (*fo)[7], -ptr[ 2]); + + *pcm1++ = SHIFT(MLZ(hi, lo)); + + ptr = *Dptr - po; + ML0(hi, lo, (*fo)[7], ptr[31 - 2]); + MLA(hi, lo, (*fo)[6], ptr[31 - 4]); + MLA(hi, lo, (*fo)[5], ptr[31 - 6]); + MLA(hi, lo, (*fo)[4], ptr[31 - 8]); + MLA(hi, lo, (*fo)[3], ptr[31 - 10]); + MLA(hi, lo, (*fo)[2], ptr[31 - 12]); + MLA(hi, lo, (*fo)[1], ptr[31 - 14]); + MLA(hi, lo, (*fo)[0], ptr[31 - 16]); + + ptr = *Dptr - pe; + MLA(hi, lo, (*fe)[0], ptr[31 - 16]); + MLA(hi, lo, (*fe)[1], ptr[31 - 14]); + MLA(hi, lo, (*fe)[2], ptr[31 - 12]); + MLA(hi, lo, (*fe)[3], ptr[31 - 10]); + MLA(hi, lo, (*fe)[4], ptr[31 - 8]); + MLA(hi, lo, (*fe)[5], ptr[31 - 6]); + MLA(hi, lo, (*fe)[6], ptr[31 - 4]); + MLA(hi, lo, (*fe)[7], ptr[31 - 2]); + + *pcm2-- = SHIFT(MLZ(hi, lo)); + + ++fo; + } + + ++Dptr; + + ptr = *Dptr + po; + ML0(hi, lo, (*fo)[0], ptr[ 0]); + MLA(hi, lo, (*fo)[1], ptr[14]); + MLA(hi, lo, (*fo)[2], ptr[12]); + MLA(hi, lo, (*fo)[3], ptr[10]); + MLA(hi, lo, (*fo)[4], ptr[ 8]); + MLA(hi, lo, (*fo)[5], ptr[ 6]); + MLA(hi, lo, (*fo)[6], ptr[ 4]); + MLA(hi, lo, (*fo)[7], ptr[ 2]); + + *pcm1 = SHIFT(-MLZ(hi, lo)); + pcm1 += 16; + + phase = (phase + 1) % 16; + } + } +} +# endif + +/* + * NAME: synth->half() + * DESCRIPTION: perform half frequency PCM synthesis + */ +static +void synth_half(struct mad_synth *synth, struct mad_frame const *frame, + unsigned int nch, unsigned int ns) +{ + unsigned int phase, ch, s, sb, pe, po; + mad_fixed_t *pcm1, *pcm2, (*filter)[2][2][16][8]; + mad_fixed_t const (*sbsample)[36][32]; + register mad_fixed_t (*fe)[8], (*fx)[8], (*fo)[8]; + register mad_fixed_t const (*Dptr)[32], *ptr; + register mad_fixed64hi_t hi; + register mad_fixed64lo_t lo; + + for (ch = 0; ch < nch; ++ch) { + sbsample = &frame->sbsample[ch]; + filter = &synth->filter[ch]; + phase = synth->phase; + pcm1 = synth->pcm.samples[ch]; + + for (s = 0; s < ns; ++s) { + dct32((*sbsample)[s], phase >> 1, + (*filter)[0][phase & 1], (*filter)[1][phase & 1]); + + pe = phase & ~1; + po = ((phase - 1) & 0xf) | 1; + + /* calculate 16 samples */ + + fe = &(*filter)[0][ phase & 1][0]; + fx = &(*filter)[0][~phase & 1][0]; + fo = &(*filter)[1][~phase & 1][0]; + + Dptr = &D[0]; + + ptr = *Dptr + pe; + ML0(hi, lo, (*fe)[0], ptr[ 0]); + MLA(hi, lo, (*fe)[1], ptr[14]); + MLA(hi, lo, (*fe)[2], ptr[12]); + MLA(hi, lo, (*fe)[3], ptr[10]); + MLA(hi, lo, (*fe)[4], ptr[ 8]); + MLA(hi, lo, (*fe)[5], ptr[ 6]); + MLA(hi, lo, (*fe)[6], ptr[ 4]); + MLA(hi, lo, (*fe)[7], ptr[ 2]); + + ptr = *Dptr + po; + MLA(hi, lo, (*fx)[0], -ptr[ 0]); + MLA(hi, lo, (*fx)[1], -ptr[14]); + MLA(hi, lo, (*fx)[2], -ptr[12]); + MLA(hi, lo, (*fx)[3], -ptr[10]); + MLA(hi, lo, (*fx)[4], -ptr[ 8]); + MLA(hi, lo, (*fx)[5], -ptr[ 6]); + MLA(hi, lo, (*fx)[6], -ptr[ 4]); + MLA(hi, lo, (*fx)[7], -ptr[ 2]); + + *pcm1++ = SHIFT(MLZ(hi, lo)); + + pcm2 = pcm1 + 14; + + for (sb = 1; sb < 16; ++sb) { + ++fe; + ++Dptr; + + /* D[32 - sb][i] == -D[sb][31 - i] */ + + if (!(sb & 1)) { + ptr = *Dptr + pe; + ML0(hi, lo, (*fe)[7], ptr[ 2]); + MLA(hi, lo, (*fe)[6], ptr[ 4]); + MLA(hi, lo, (*fe)[5], ptr[ 6]); + MLA(hi, lo, (*fe)[4], ptr[ 8]); + MLA(hi, lo, (*fe)[3], ptr[10]); + MLA(hi, lo, (*fe)[2], ptr[12]); + MLA(hi, lo, (*fe)[1], ptr[14]); + MLA(hi, lo, (*fe)[0], ptr[ 0]); + + ptr = *Dptr + po; + MLA(hi, lo, (*fo)[0], -ptr[ 0]); + MLA(hi, lo, (*fo)[1], -ptr[14]); + MLA(hi, lo, (*fo)[2], -ptr[12]); + MLA(hi, lo, (*fo)[3], -ptr[10]); + MLA(hi, lo, (*fo)[4], -ptr[ 8]); + MLA(hi, lo, (*fo)[5], -ptr[ 6]); + MLA(hi, lo, (*fo)[6], -ptr[ 4]); + MLA(hi, lo, (*fo)[7], -ptr[ 2]); + + *pcm1++ = SHIFT(MLZ(hi, lo)); + + ptr = *Dptr - po; + ML0(hi, lo, (*fo)[7], ptr[31 - 2]); + MLA(hi, lo, (*fo)[6], ptr[31 - 4]); + MLA(hi, lo, (*fo)[5], ptr[31 - 6]); + MLA(hi, lo, (*fo)[4], ptr[31 - 8]); + MLA(hi, lo, (*fo)[3], ptr[31 - 10]); + MLA(hi, lo, (*fo)[2], ptr[31 - 12]); + MLA(hi, lo, (*fo)[1], ptr[31 - 14]); + MLA(hi, lo, (*fo)[0], ptr[31 - 16]); + + ptr = *Dptr - pe; + MLA(hi, lo, (*fe)[0], ptr[31 - 16]); + MLA(hi, lo, (*fe)[1], ptr[31 - 14]); + MLA(hi, lo, (*fe)[2], ptr[31 - 12]); + MLA(hi, lo, (*fe)[3], ptr[31 - 10]); + MLA(hi, lo, (*fe)[4], ptr[31 - 8]); + MLA(hi, lo, (*fe)[5], ptr[31 - 6]); + MLA(hi, lo, (*fe)[6], ptr[31 - 4]); + MLA(hi, lo, (*fe)[7], ptr[31 - 2]); + + *pcm2-- = SHIFT(MLZ(hi, lo)); + } + + ++fo; + } + + ++Dptr; + + ptr = *Dptr + po; + ML0(hi, lo, (*fo)[0], ptr[ 0]); + MLA(hi, lo, (*fo)[1], ptr[14]); + MLA(hi, lo, (*fo)[2], ptr[12]); + MLA(hi, lo, (*fo)[3], ptr[10]); + MLA(hi, lo, (*fo)[4], ptr[ 8]); + MLA(hi, lo, (*fo)[5], ptr[ 6]); + MLA(hi, lo, (*fo)[6], ptr[ 4]); + MLA(hi, lo, (*fo)[7], ptr[ 2]); + + *pcm1 = SHIFT(-MLZ(hi, lo)); + pcm1 += 8; + + phase = (phase + 1) % 16; + } + } +} + +/* + * NAME: synth->frame() + * DESCRIPTION: perform PCM synthesis of frame subband samples + */ +void mad_synth_frame(struct mad_synth *synth, struct mad_frame const *frame) +{ + unsigned int nch, ns; + void (*synth_frame)(struct mad_synth *, struct mad_frame const *, + unsigned int, unsigned int); + + nch = MAD_NCHANNELS(&frame->header); + ns = MAD_NSBSAMPLES(&frame->header); + + synth->pcm.samplerate = frame->header.samplerate; + synth->pcm.channels = nch; + synth->pcm.length = 32 * ns; + + synth_frame = synth_full; + + if (frame->options & MAD_OPTION_HALFSAMPLERATE) { + synth->pcm.samplerate /= 2; + synth->pcm.length /= 2; + + synth_frame = synth_half; + } + + synth_frame(synth, frame, nch, ns); + + synth->phase = (synth->phase + ns) % 16; +} diff --git a/core/multimedia/opieplayer/libmad/synth.h b/core/multimedia/opieplayer/libmad/synth.h new file mode 100644 index 0000000..64f6a86 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/synth.h @@ -0,0 +1,50 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_SYNTH_H +# define LIBMAD_SYNTH_H + +# include "fixed.h" +# include "frame.h" + +struct mad_synth { + mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */ + /* [ch][eo][peo][s][v] */ + + unsigned int phase; /* current processing phase */ + + struct mad_pcm { + unsigned int samplerate; /* sampling frequency (Hz) */ + unsigned short channels; /* number of channels */ + unsigned short length; /* number of samples per channel */ + mad_fixed_t samples[2][1152]; /* PCM output samples */ + } pcm; +}; + +void mad_synth_init(struct mad_synth *); + +# define mad_synth_finish(synth) /* nothing */ + +void mad_synth_mute(struct mad_synth *); + +void mad_synth_frame(struct mad_synth *, struct mad_frame const *); + +# endif diff --git a/core/multimedia/opieplayer/libmad/timer.c b/core/multimedia/opieplayer/libmad/timer.c new file mode 100644 index 0000000..b30680c --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/timer.c @@ -0,0 +1,480 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifdef HAVE_CONFIG_H +# include "libmad_config.h" +# endif + +# include "libmad_global.h" + +# include +# include + +# include "timer.h" + +mad_timer_t const mad_timer_zero = { 0, 0 }; + +/* + * NAME: timer->compare() + * DESCRIPTION: indicate relative order of two timers + */ +int mad_timer_compare(mad_timer_t timer1, mad_timer_t timer2) +{ + signed long diff; + + diff = timer1.seconds - timer2.seconds; + if (diff < 0) + return -1; + else if (diff > 0) + return +1; + + diff = timer1.fraction - timer2.fraction; + if (diff < 0) + return -1; + else if (diff > 0) + return +1; + + return 0; +} + +/* + * NAME: timer->negate() + * DESCRIPTION: invert the sign of a timer + */ +void mad_timer_negate(mad_timer_t *timer) +{ + timer->seconds = -timer->seconds; + + if (timer->fraction) { + timer->seconds -= 1; + timer->fraction = MAD_TIMER_RESOLUTION - timer->fraction; + } +} + +/* + * NAME: timer->abs() + * DESCRIPTION: return the absolute value of a timer + */ +mad_timer_t mad_timer_abs(mad_timer_t timer) +{ + if (mad_timer_sign(timer) < 0) + mad_timer_negate(&timer); + + return timer; +} + +/* + * NAME: reduce_timer() + * DESCRIPTION: carry timer fraction into seconds + */ +static +void reduce_timer(mad_timer_t *timer) +{ + timer->seconds += timer->fraction / MAD_TIMER_RESOLUTION; + timer->fraction %= MAD_TIMER_RESOLUTION; +} + +/* + * NAME: gcd() + * DESCRIPTION: compute greatest common denominator + */ +static +unsigned long gcd(unsigned long num1, unsigned long num2) +{ + unsigned long tmp; + + while (num2) { + tmp = num2; + num2 = num1 % num2; + num1 = tmp; + } + + return num1; +} + +/* + * NAME: reduce_rational() + * DESCRIPTION: convert rational expression to lowest terms + */ +static +void reduce_rational(unsigned long *numer, unsigned long *denom) +{ + unsigned long factor; + + factor = gcd(*numer, *denom); + + assert(factor != 0); + + *numer /= factor; + *denom /= factor; +} + +/* + * NAME: scale_rational() + * DESCRIPTION: solve numer/denom == ?/scale avoiding overflowing + */ +static +unsigned long scale_rational(unsigned long numer, unsigned long denom, + unsigned long scale) +{ + reduce_rational(&numer, &denom); + reduce_rational(&scale, &denom); + + assert(denom != 0); + + if (denom < scale) + return numer * (scale / denom) + numer * (scale % denom) / denom; + if (denom < numer) + return scale * (numer / denom) + scale * (numer % denom) / denom; + + return numer * scale / denom; +} + +/* + * NAME: timer->set() + * DESCRIPTION: set timer to specific value + */ +void mad_timer_set(mad_timer_t *timer, unsigned long seconds, + unsigned long fraction, unsigned long fracparts) +{ + timer->seconds = seconds; + + if (fraction == 0) + fracparts = 0; + else if (fracparts == 0) { + fracparts = fraction; + fraction = 1; + } + + switch (fracparts) { + case 0: + timer->fraction = 0; + break; + + case MAD_TIMER_RESOLUTION: + timer->fraction = fraction; + break; + + case 8000: + timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 8000); + break; + + case 11025: + timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 11025); + break; + + case 12000: + timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 12000); + break; + + case 16000: + timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 16000); + break; + + case 22050: + timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 22050); + break; + + case 24000: + timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 24000); + break; + + case 32000: + timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 32000); + break; + + case 44100: + timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 44100); + break; + + case 48000: + timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 48000); + break; + + default: + timer->fraction = + scale_rational(fraction, fracparts, MAD_TIMER_RESOLUTION); + break; + } + + if (timer->fraction >= MAD_TIMER_RESOLUTION) + reduce_timer(timer); +} + +/* + * NAME: timer->add() + * DESCRIPTION: add one timer to another + */ +void mad_timer_add(mad_timer_t *timer, mad_timer_t incr) +{ + timer->seconds += incr.seconds; + timer->fraction += incr.fraction; + + if (timer->fraction >= MAD_TIMER_RESOLUTION) + reduce_timer(timer); +} + +/* + * NAME: timer->multiply() + * DESCRIPTION: multiply a timer by a scalar value + */ +void mad_timer_multiply(mad_timer_t *timer, signed long scalar) +{ + mad_timer_t addend; + unsigned long factor; + + factor = scalar; + if (scalar < 0) { + mad_timer_negate(timer); + factor = -scalar; + } + + addend = *timer; + *timer = mad_timer_zero; + + while (factor) { + if (factor & 1) + mad_timer_add(timer, addend); + + mad_timer_add(&addend, addend); + factor >>= 1; + } +} + +/* + * NAME: timer->count() + * DESCRIPTION: return timer value in selected units + */ +signed long mad_timer_count(mad_timer_t timer, enum mad_units units) +{ + switch (units) { + case MAD_UNITS_HOURS: + return timer.seconds / 60 / 60; + + case MAD_UNITS_MINUTES: + return timer.seconds / 60; + + case MAD_UNITS_SECONDS: + return timer.seconds; + + case MAD_UNITS_DECISECONDS: + case MAD_UNITS_CENTISECONDS: + case MAD_UNITS_MILLISECONDS: + + case MAD_UNITS_8000_HZ: + case MAD_UNITS_11025_HZ: + case MAD_UNITS_12000_HZ: + case MAD_UNITS_16000_HZ: + case MAD_UNITS_22050_HZ: + case MAD_UNITS_24000_HZ: + case MAD_UNITS_32000_HZ: + case MAD_UNITS_44100_HZ: + case MAD_UNITS_48000_HZ: + + case MAD_UNITS_24_FPS: + case MAD_UNITS_25_FPS: + case MAD_UNITS_30_FPS: + case MAD_UNITS_48_FPS: + case MAD_UNITS_50_FPS: + case MAD_UNITS_60_FPS: + case MAD_UNITS_75_FPS: + return timer.seconds * (signed long) units + + (signed long) scale_rational(timer.fraction, MAD_TIMER_RESOLUTION, + units); + + case MAD_UNITS_23_976_FPS: + case MAD_UNITS_24_975_FPS: + case MAD_UNITS_29_97_FPS: + case MAD_UNITS_47_952_FPS: + case MAD_UNITS_49_95_FPS: + case MAD_UNITS_59_94_FPS: + return (mad_timer_count(timer, -units) + 1) * 1000 / 1001; + } + + /* unsupported units */ + return 0; +} + +/* + * NAME: timer->fraction() + * DESCRIPTION: return fractional part of timer in arbitrary terms + */ +unsigned long mad_timer_fraction(mad_timer_t timer, unsigned long fracparts) +{ + timer = mad_timer_abs(timer); + + switch (fracparts) { + case 0: + return MAD_TIMER_RESOLUTION / timer.fraction; + + case MAD_TIMER_RESOLUTION: + return timer.fraction; + + default: + return scale_rational(timer.fraction, MAD_TIMER_RESOLUTION, fracparts); + } +} + +/* + * NAME: timer->string() + * DESCRIPTION: write a string representation of a timer using a template + */ +void mad_timer_string(mad_timer_t timer, + char *dest, char const *format, enum mad_units units, + enum mad_units fracunits, unsigned long subparts) +{ + unsigned long hours, minutes, seconds, sub; + unsigned int frac; + + timer = mad_timer_abs(timer); + + seconds = timer.seconds; + frac = sub = 0; + + switch (fracunits) { + case MAD_UNITS_HOURS: + case MAD_UNITS_MINUTES: + case MAD_UNITS_SECONDS: + break; + + case MAD_UNITS_DECISECONDS: + case MAD_UNITS_CENTISECONDS: + case MAD_UNITS_MILLISECONDS: + + case MAD_UNITS_8000_HZ: + case MAD_UNITS_11025_HZ: + case MAD_UNITS_12000_HZ: + case MAD_UNITS_16000_HZ: + case MAD_UNITS_22050_HZ: + case MAD_UNITS_24000_HZ: + case MAD_UNITS_32000_HZ: + case MAD_UNITS_44100_HZ: + case MAD_UNITS_48000_HZ: + + case MAD_UNITS_24_FPS: + case MAD_UNITS_25_FPS: + case MAD_UNITS_30_FPS: + case MAD_UNITS_48_FPS: + case MAD_UNITS_50_FPS: + case MAD_UNITS_60_FPS: + case MAD_UNITS_75_FPS: + { + unsigned long fracparts; + + fracparts = MAD_TIMER_RESOLUTION / fracunits; + + frac = timer.fraction / fracparts; + sub = scale_rational(timer.fraction % fracparts, fracparts, subparts); + } + break; + + case MAD_UNITS_23_976_FPS: + case MAD_UNITS_24_975_FPS: + case MAD_UNITS_29_97_FPS: + case MAD_UNITS_47_952_FPS: + case MAD_UNITS_49_95_FPS: + case MAD_UNITS_59_94_FPS: + /* drop-frame encoding */ + /* N.B. this is only well-defined for MAD_UNITS_29_97_FPS */ + { + unsigned long frame, cycle, d, m; + + frame = mad_timer_count(timer, fracunits); + + cycle = -fracunits * 60 * 10 - (10 - 1) * 2; + + d = frame / cycle; + m = frame % cycle; + frame += (10 - 1) * 2 * d; + if (m > 2) + frame += 2 * ((m - 2) / (cycle / 10)); + + frac = frame % -fracunits; + seconds = frame / -fracunits; + } + break; + } + + switch (units) { + case MAD_UNITS_HOURS: + minutes = seconds / 60; + hours = minutes / 60; + + sprintf(dest, format, + hours, + (unsigned int) (minutes % 60), + (unsigned int) (seconds % 60), + frac, sub); + break; + + case MAD_UNITS_MINUTES: + minutes = seconds / 60; + + sprintf(dest, format, + minutes, + (unsigned int) (seconds % 60), + frac, sub); + break; + + case MAD_UNITS_SECONDS: + sprintf(dest, format, + seconds, + frac, sub); + break; + + case MAD_UNITS_23_976_FPS: + case MAD_UNITS_24_975_FPS: + case MAD_UNITS_29_97_FPS: + case MAD_UNITS_47_952_FPS: + case MAD_UNITS_49_95_FPS: + case MAD_UNITS_59_94_FPS: + if (fracunits < 0) { + /* not yet implemented */ + sub = 0; + } + + /* fall through */ + + case MAD_UNITS_DECISECONDS: + case MAD_UNITS_CENTISECONDS: + case MAD_UNITS_MILLISECONDS: + + case MAD_UNITS_8000_HZ: + case MAD_UNITS_11025_HZ: + case MAD_UNITS_12000_HZ: + case MAD_UNITS_16000_HZ: + case MAD_UNITS_22050_HZ: + case MAD_UNITS_24000_HZ: + case MAD_UNITS_32000_HZ: + case MAD_UNITS_44100_HZ: + case MAD_UNITS_48000_HZ: + + case MAD_UNITS_24_FPS: + case MAD_UNITS_25_FPS: + case MAD_UNITS_30_FPS: + case MAD_UNITS_48_FPS: + case MAD_UNITS_50_FPS: + case MAD_UNITS_60_FPS: + case MAD_UNITS_75_FPS: + sprintf(dest, format, mad_timer_count(timer, units), sub); + break; + } +} diff --git a/core/multimedia/opieplayer/libmad/timer.h b/core/multimedia/opieplayer/libmad/timer.h new file mode 100644 index 0000000..67fe16a --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/timer.h @@ -0,0 +1,100 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifndef LIBMAD_TIMER_H +# define LIBMAD_TIMER_H + +typedef struct { + signed long seconds; /* whole seconds */ + unsigned long fraction; /* 1/MAD_TIMER_RESOLUTION seconds */ +} mad_timer_t; + +extern mad_timer_t const mad_timer_zero; + +# define MAD_TIMER_RESOLUTION 352800000UL + +enum mad_units { + MAD_UNITS_HOURS = -2, + MAD_UNITS_MINUTES = -1, + MAD_UNITS_SECONDS = 0, + + /* metric units */ + + MAD_UNITS_DECISECONDS = 10, + MAD_UNITS_CENTISECONDS = 100, + MAD_UNITS_MILLISECONDS = 1000, + + /* audio sample units */ + + MAD_UNITS_8000_HZ = 8000, + MAD_UNITS_11025_HZ = 11025, + MAD_UNITS_12000_HZ = 12000, + + MAD_UNITS_16000_HZ = 16000, + MAD_UNITS_22050_HZ = 22050, + MAD_UNITS_24000_HZ = 24000, + + MAD_UNITS_32000_HZ = 32000, + MAD_UNITS_44100_HZ = 44100, + MAD_UNITS_48000_HZ = 48000, + + /* video frame/field units */ + + MAD_UNITS_24_FPS = 24, + MAD_UNITS_25_FPS = 25, + MAD_UNITS_30_FPS = 30, + MAD_UNITS_48_FPS = 48, + MAD_UNITS_50_FPS = 50, + MAD_UNITS_60_FPS = 60, + + /* CD audio frames */ + + MAD_UNITS_75_FPS = 75, + + /* video drop-frame units */ + + MAD_UNITS_23_976_FPS = -24, + MAD_UNITS_24_975_FPS = -25, + MAD_UNITS_29_97_FPS = -30, + MAD_UNITS_47_952_FPS = -48, + MAD_UNITS_49_95_FPS = -50, + MAD_UNITS_59_94_FPS = -60 +}; + +# define mad_timer_reset(timer) (*(timer) = mad_timer_zero) + +int mad_timer_compare(mad_timer_t, mad_timer_t); + +# define mad_timer_sign(timer) mad_timer_compare((timer), mad_timer_zero) + +void mad_timer_negate(mad_timer_t *); +mad_timer_t mad_timer_abs(mad_timer_t); + +void mad_timer_set(mad_timer_t *, unsigned long, unsigned long, unsigned long); +void mad_timer_add(mad_timer_t *, mad_timer_t); +void mad_timer_multiply(mad_timer_t *, signed long); + +signed long mad_timer_count(mad_timer_t, enum mad_units); +unsigned long mad_timer_fraction(mad_timer_t, unsigned long); +void mad_timer_string(mad_timer_t, char *, char const *, + enum mad_units, enum mad_units, unsigned long); + +# endif diff --git a/core/multimedia/opieplayer/libmad/version.c b/core/multimedia/opieplayer/libmad/version.c new file mode 100644 index 0000000..413d54b --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/version.c @@ -0,0 +1,91 @@ +/* + * mad - MPEG audio decoder + * Copyright (C) 2000-2001 Robert Leslie + * + * 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 + * + * $Id$ + */ + +# ifdef HAVE_CONFIG_H +# include "libmad_config.h" +# endif + +# include "libmad_global.h" + +# include "libmad_version.h" + +char const mad_version[] = "MPEG Audio Decoder version " MAD_VERSION; +char const mad_copyright[] = "Copyright (C) " MAD_PUBLISHYEAR " " MAD_AUTHOR; +char const mad_author[] = MAD_AUTHOR " <" MAD_EMAIL ">"; + +char const mad_build[] = +# if defined(FPM_64BIT) + "FPM_64BIT " +# elif defined(FPM_INTEL) + "FPM_INTEL " +# elif defined(FPM_ARM) + "FPM_ARM " +# elif defined(FPM_MIPS) + "FPM_MIPS " +# elif defined(FPM_SPARC) + "FPM_SPARC " +# elif defined(FPM_PPC) + "FPM_PPC " +# elif defined(FPM_DEFAULT) + "FPM_DEFAULT " +# endif + +# if defined(ASO_IMDCT) + "ASO_IMDCT " +# endif +# if defined(ASO_INTERLEAVE1) + "ASO_INTERLEAVE1 " +# endif +# if defined(ASO_INTERLEAVE2) + "ASO_INTERLEAVE2 " +# endif +# if defined(ASO_ZEROCHECK) + "ASO_ZEROCHECK " +# endif + +# if defined(OPT_SPEED) + "OPT_SPEED " +# elif defined(OPT_ACCURACY) + "OPT_ACCURACY " +# endif + +# if defined(OPT_SSO) + "OPT_SSO " +# endif + +# if defined(OPT_DCTO) /* never defined here */ + "OPT_DCTO " +# endif + +# if defined(OPT_STRICT) + "OPT_STRICT " +# endif + +# if defined(EXPERIMENTAL) + "EXPERIMENTAL " +# endif + +# if defined(DEBUG) + "DEBUG " +# elif defined(NDEBUG) + "NDEBUG " +# endif +; diff --git a/core/multimedia/opieplayer/libmpeg3/.cvsignore b/core/multimedia/opieplayer/libmpeg3/.cvsignore new file mode 100644 index 0000000..d7bb3c1 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/.cvsignore @@ -0,0 +1,5 @@ +global_config +dump +mpeg3toc +mpeg3cat +Makefile diff --git a/core/multimedia/opieplayer/libmpeg3/COPYING b/core/multimedia/opieplayer/libmpeg3/COPYING new file mode 100644 index 0000000..60549be --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. + + + Copyright (C) 19yy + + 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 + + +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) 19yy 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. + + , 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. diff --git a/core/multimedia/opieplayer/libmpeg3/Makefile.in b/core/multimedia/opieplayer/libmpeg3/Makefile.in new file mode 100644 index 0000000..1817902 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/Makefile.in @@ -0,0 +1,774 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB) -DQCONFIG=\"qpe\" +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB) -DQCONFIG=\"qpe\" +INCPATH = -I$(QPEDIR)/include -I.. +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe -lpthread -lm $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../../plugins/codecs/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = mpeg3plugin +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = libmpeg3plugin.h \ + libmpeg3pluginimpl.h +SOURCES = libmpeg3plugin.cpp \ + libmpeg3pluginimpl.cpp \ + bitstream.c \ + libmpeg3.c \ + mpeg3atrack.c \ + mpeg3css.c \ + mpeg3demux.c \ + mpeg3io.c \ + mpeg3title.c \ + mpeg3vtrack.c \ + audio/ac3.c \ + audio/bit_allocation.c \ + audio/dct.c \ + audio/exponents.c \ + audio/header.c \ + audio/layer2.c \ + audio/layer3.c \ + audio/mantissa.c \ + audio/mpeg3audio.c \ + audio/pcm.c \ + audio/synthesizers.c \ + audio/tables.c \ + video/getpicture.c \ + video/headers.c \ + video/idct.c \ + video/macroblocks.c \ + video/mmxtest.c \ + video/motion.c \ + video/mpeg3video.c \ + video/output.c \ + video/reconstruct.c \ + video/seek.c \ + video/slice.c \ + video/vlc.c +OBJECTS = libmpeg3plugin.o \ + libmpeg3pluginimpl.o \ + bitstream.o \ + libmpeg3.o \ + mpeg3atrack.o \ + mpeg3css.o \ + mpeg3demux.o \ + mpeg3io.o \ + mpeg3title.o \ + mpeg3vtrack.o \ + audio/ac3.o \ + audio/bit_allocation.o \ + audio/dct.o \ + audio/exponents.o \ + audio/header.o \ + audio/layer2.o \ + audio/layer3.o \ + audio/mantissa.o \ + audio/mpeg3audio.o \ + audio/pcm.o \ + audio/synthesizers.o \ + audio/tables.o \ + video/getpicture.o \ + video/headers.o \ + video/idct.o \ + video/macroblocks.o \ + video/mmxtest.o \ + video/motion.o \ + video/mpeg3video.o \ + video/output.o \ + video/reconstruct.o \ + video/seek.o \ + video/slice.o \ + video/vlc.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = +OBJMOC = + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(SYSCONF_LINK_TARGET) + +$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK_LIB) + +moc: $(SRCMOC) + +tmake: + tmake libmpeg3.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +libmpeg3plugin.o: libmpeg3plugin.cpp \ + libmpeg3plugin.h \ + libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + mpeg3protos.h \ + ../mediaplayerplugininterface.h + +libmpeg3pluginimpl.o: libmpeg3pluginimpl.cpp \ + libmpeg3plugin.h \ + libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + mpeg3protos.h \ + ../mediaplayerplugininterface.h \ + libmpeg3pluginimpl.h \ + ../mediaplayerplugininterface.h + +bitstream.o: bitstream.c \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + mpeg3protos.h + +libmpeg3.o: libmpeg3.c \ + libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + mpeg3protos.h + +mpeg3atrack.o: mpeg3atrack.c \ + libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + mpeg3protos.h + +mpeg3css.o: mpeg3css.c \ + mpeg3css.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h + +mpeg3demux.o: mpeg3demux.c \ + libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + mpeg3protos.h + +mpeg3io.o: mpeg3io.c \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + mpeg3protos.h + +mpeg3title.o: mpeg3title.c \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + mpeg3protos.h + +mpeg3vtrack.o: mpeg3vtrack.c \ + libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + mpeg3protos.h + +audio/ac3.o: audio/ac3.c \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h + +audio/bit_allocation.o: audio/bit_allocation.c \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h + +audio/dct.o: audio/dct.c \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h \ + audio/tables.h \ + audio/fptables.h + +audio/exponents.o: audio/exponents.c \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h + +audio/header.o: audio/header.c \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/tables.h \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h + +audio/layer2.o: audio/layer2.c \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h \ + audio/tables.h + +audio/layer3.o: audio/layer3.c \ + audio/huffman.h \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h \ + audio/tables.h + +audio/mantissa.o: audio/mantissa.c \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h + +audio/mpeg3audio.o: audio/mpeg3audio.c \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h \ + audio/mpeg3audio.h \ + audio/tables.h + +audio/pcm.o: audio/pcm.c \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h + +audio/synthesizers.o: audio/synthesizers.c \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h \ + audio/tables.h + +audio/tables.o: audio/tables.c \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + audio/../mpeg3protos.h \ + audio/tables.h \ + audio/fptables.h + +video/getpicture.o: video/getpicture.c \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + video/../mpeg3private.inc \ + video/idct.h \ + video/slice.h \ + video/../timecode.h \ + video/../mpeg3protos.h \ + video/mpeg3video.h \ + video/vlc.h + +video/headers.o: video/headers.c \ + video/../mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + video/../mpeg3private.inc \ + video/idct.h \ + video/slice.h \ + video/../timecode.h \ + video/../mpeg3protos.h \ + video/mpeg3video.h + +video/idct.o: video/idct.c \ + video/idct.h + +video/macroblocks.o: video/macroblocks.c \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + video/../mpeg3private.inc \ + video/idct.h \ + video/slice.h \ + video/../timecode.h \ + video/../mpeg3protos.h \ + video/mpeg3video.h \ + video/vlc.h + +video/mmxtest.o: video/mmxtest.c \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + video/../mpeg3private.inc \ + video/idct.h \ + video/slice.h \ + video/../timecode.h \ + video/../mpeg3protos.h + +video/motion.o: video/motion.c \ + video/mpeg3video.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + video/../mpeg3private.inc \ + video/idct.h \ + video/slice.h \ + video/../timecode.h \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + video/../mpeg3protos.h \ + video/vlc.h + +video/mpeg3video.o: video/mpeg3video.c \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + video/../mpeg3private.inc \ + video/idct.h \ + video/slice.h \ + video/../timecode.h \ + video/../mpeg3protos.h \ + video/mpeg3video.h \ + video/mpeg3videoprotos.h + +video/output.o: video/output.c \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + video/../mpeg3private.inc \ + video/idct.h \ + video/slice.h \ + video/../timecode.h \ + video/../mpeg3protos.h \ + video/mpeg3video.h + +video/reconstruct.o: video/reconstruct.c \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + video/../mpeg3private.inc \ + video/idct.h \ + video/slice.h \ + video/../timecode.h \ + video/../mpeg3protos.h \ + video/mpeg3video.h + +video/seek.o: video/seek.c \ + video/../mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + video/../mpeg3private.inc \ + video/idct.h \ + video/slice.h \ + video/../timecode.h \ + video/../mpeg3protos.h \ + video/mpeg3video.h + +video/slice.o: video/slice.c \ + audio/../libmpeg3.h \ + mpeg3private.h \ + mpeg3atrack.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + audio/mpeg3audio.h \ + audio/ac3.h \ + audio/mpeg3real.h \ + audio/../bitstream.h \ + mpeg3vtrack.h \ + video/mpeg3video.h \ + video/../mpeg3private.inc \ + video/idct.h \ + video/slice.h \ + video/../timecode.h \ + video/../mpeg3protos.h \ + video/mpeg3video.h \ + video/mpeg3videoprotos.h + +video/vlc.o: video/vlc.c \ + video/mpeg3video.h \ + audio/../bitstream.h \ + mpeg3demux.h \ + mpeg3title.h \ + mpeg3io.h \ + mpeg3css.h \ + mpeg3private.inc \ + video/../mpeg3private.inc \ + video/idct.h \ + video/slice.h \ + video/../timecode.h \ + video/vlc.h + + diff --git a/core/multimedia/opieplayer/libmpeg3/README b/core/multimedia/opieplayer/libmpeg3/README new file mode 100644 index 0000000..7a2a061 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/README @@ -0,0 +1,35 @@ +/******************************************************** + * LibMPEG3 + * Author: Adam Williams + * Page: heroine.linuxbox.com + * + * libmpeg3 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. + * + * libmpeg3 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. + * + *******************************************************/ + + +/********************************************************** + * Credits: + *********************************************************/ + +AC3 decoder: + + Written by Aaron Holtzman (aholtzma@engr.uvic.ca) + + + +Problems: + + Streams where the multiplexing packet size changes at random. diff --git a/core/multimedia/opieplayer/libmpeg3/VERSION b/core/multimedia/opieplayer/libmpeg3/VERSION new file mode 100644 index 0000000..55772e2 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/VERSION @@ -0,0 +1 @@ +libmpeg3-1.2.1 diff --git a/core/multimedia/opieplayer/libmpeg3/audio/Makefile b/core/multimedia/opieplayer/libmpeg3/audio/Makefile new file mode 100644 index 0000000..eaa0e0b --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/Makefile @@ -0,0 +1,35 @@ +include ../global_config +export CFLAGS +export CFLAGS_lessopt + +OBJS = \ + ac3.o \ + bit_allocation.o \ + dct.o \ + exponents.o \ + header.o \ + layer2.o \ + layer3.o \ + mantissa.o \ + mpeg3audio.o \ + pcm.o \ + synthesizers.o \ + tables.o + +all: $(OBJS) + +dct.o: dct.c + $(CC) -c `./c_flags dct.c` -o $@ $< + +synthesizers.o: synthesizers.c + $(CC) -c `./c_flags synthesizers.c` -o $@ $< + + +.c.o: + $(CC) -c `./c_flags` -o $@ $< + +.s.o: + $(CC) -f elf $*.s + +clean: + rm -f *.o diff --git a/core/multimedia/opieplayer/libmpeg3/audio/ac3.c b/core/multimedia/opieplayer/libmpeg3/audio/ac3.c new file mode 100644 index 0000000..7a3b664 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/ac3.c @@ -0,0 +1,691 @@ +/* + * + * ac3.c Copyright (C) Aaron Holtzman - May 1999 + * + * + * This file is part of libmpeg3 + * + * libmpeg3 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. + * + * libmpeg3 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. + * + */ + +#include "mpeg3audio.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" + +#include +#include +#include +#include + +#define MPEG3AC3_MAGIC_NUMBER 0xdeadbeef + + +int mpeg3_ac3_samplerates[] = { 48000, 44100, 32000 }; + +struct mpeg3_framesize_s +{ + unsigned short bit_rate; + unsigned short frm_size[3]; +}; + +struct mpeg3_framesize_s framesize_codes[] = +{ + { 32 ,{64 ,69 ,96 } }, + { 32 ,{64 ,70 ,96 } }, + { 40 ,{80 ,87 ,120 } }, + { 40 ,{80 ,88 ,120 } }, + { 48 ,{96 ,104 ,144 } }, + { 48 ,{96 ,105 ,144 } }, + { 56 ,{112 ,121 ,168 } }, + { 56 ,{112 ,122 ,168 } }, + { 64 ,{128 ,139 ,192 } }, + { 64 ,{128 ,140 ,192 } }, + { 80 ,{160 ,174 ,240 } }, + { 80 ,{160 ,175 ,240 } }, + { 96 ,{192 ,208 ,288 } }, + { 96 ,{192 ,209 ,288 } }, + { 112 ,{224 ,243 ,336 } }, + { 112 ,{224 ,244 ,336 } }, + { 128 ,{256 ,278 ,384 } }, + { 128 ,{256 ,279 ,384 } }, + { 160 ,{320 ,348 ,480 } }, + { 160 ,{320 ,349 ,480 } }, + { 192 ,{384 ,417 ,576 } }, + { 192 ,{384 ,418 ,576 } }, + { 224 ,{448 ,487 ,672 } }, + { 224 ,{448 ,488 ,672 } }, + { 256 ,{512 ,557 ,768 } }, + { 256 ,{512 ,558 ,768 } }, + { 320 ,{640 ,696 ,960 } }, + { 320 ,{640 ,697 ,960 } }, + { 384 ,{768 ,835 ,1152 } }, + { 384 ,{768 ,836 ,1152 } }, + { 448 ,{896 ,975 ,1344 } }, + { 448 ,{896 ,976 ,1344 } }, + { 512 ,{1024 ,1114 ,1536 } }, + { 512 ,{1024 ,1115 ,1536 } }, + { 576 ,{1152 ,1253 ,1728 } }, + { 576 ,{1152 ,1254 ,1728 } }, + { 640 ,{1280 ,1393 ,1920 } }, + { 640 ,{1280 ,1394 ,1920 } } +}; + +/* Audio channel modes */ +short mpeg3_ac3_acmodes[] = {2, 1, 2, 3, 3, 4, 4, 5}; + +/* Rematrix tables */ +struct rematrix_band_s +{ + int start; + int end; +}; + +struct rematrix_band_s mpeg3_rematrix_band[] = +{ + {13, 24}, + {25, 36}, + {37, 60}, + {61, 252} +}; + +int mpeg3_min(int x, int y) +{ + return (x < y) ? x : y; +} + +int mpeg3_max(int x, int y) +{ + return (x > y) ? x : y; +} + +int mpeg3audio_read_ac3_header(mpeg3audio_t *audio) +{ + unsigned int code, crc; + unsigned int i; + mpeg3_ac3bsi_t *bsi = &(audio->ac3_bsi); + +/* Get the sync code */ + code = mpeg3bits_getbits(audio->astream, 16); + while(!mpeg3bits_eof(audio->astream) && code != MPEG3_AC3_START_CODE) + { + code <<= 8; + code &= 0xffff; + code |= mpeg3bits_getbits(audio->astream, 8); + } + + if(mpeg3bits_eof(audio->astream)) return 1; + +/* Get crc1 - we don't actually use this data though */ +/* The crc can be the same as the sync code or come after a sync code repeated twice */ + crc = mpeg3bits_getbits(audio->astream, 16); + +/* Got the sync code. Read the entire frame into a buffer if possible. */ + if(audio->avg_framesize > 0) + { + if(mpeg3bits_read_buffer(audio->astream, audio->ac3_buffer, audio->framesize - 4)) + return 1; + mpeg3bits_use_ptr(audio->astream, audio->ac3_buffer); + } + +/* Get the sampling rate code */ + audio->sampling_frequency_code = mpeg3bits_getbits(audio->astream, 2); + +/* Get the frame size code */ + audio->ac3_framesize_code = mpeg3bits_getbits(audio->astream, 6); + + audio->bitrate = framesize_codes[audio->ac3_framesize_code].bit_rate; + audio->avg_framesize = audio->framesize = 2 * framesize_codes[audio->ac3_framesize_code].frm_size[audio->sampling_frequency_code]; + +/* Check the AC-3 version number */ + bsi->bsid = mpeg3bits_getbits(audio->astream, 5); + +/* Get the audio service provided by the steram */ + bsi->bsmod = mpeg3bits_getbits(audio->astream, 3); + +/* Get the audio coding mode (ie how many channels)*/ + bsi->acmod = mpeg3bits_getbits(audio->astream, 3); + +/* Predecode the number of full bandwidth channels as we use this + * number a lot */ + bsi->nfchans = mpeg3_ac3_acmodes[bsi->acmod]; + audio->channels = bsi->nfchans; + +/* If it is in use, get the centre channel mix level */ + if((bsi->acmod & 0x1) && (bsi->acmod != 0x1)) + bsi->cmixlev = mpeg3bits_getbits(audio->astream, 2); + +/* If it is in use, get the surround channel mix level */ + if(bsi->acmod & 0x4) + bsi->surmixlev = mpeg3bits_getbits(audio->astream, 2); + +/* Get the dolby surround mode if in 2/0 mode */ + if(bsi->acmod == 0x2) + bsi->dsurmod= mpeg3bits_getbits(audio->astream, 2); + +/* Is the low frequency effects channel on? */ + bsi->lfeon = mpeg3bits_getbits(audio->astream, 1); + +/* Get the dialogue normalization level */ + bsi->dialnorm = mpeg3bits_getbits(audio->astream, 5); + +/* Does compression gain exist? */ + bsi->compre = mpeg3bits_getbits(audio->astream, 1); + if (bsi->compre) + { +/* Get compression gain */ + bsi->compr = mpeg3bits_getbits(audio->astream, 8); + } + +/* Does language code exist? */ + bsi->langcode = mpeg3bits_getbits(audio->astream, 1); + if (bsi->langcode) + { +/* Get langauge code */ + bsi->langcod = mpeg3bits_getbits(audio->astream, 8); + } + +/* Does audio production info exist? */ + bsi->audprodie = mpeg3bits_getbits(audio->astream, 1); + if (bsi->audprodie) + { +/* Get mix level */ + bsi->mixlevel = mpeg3bits_getbits(audio->astream, 5); + +/* Get room type */ + bsi->roomtyp = mpeg3bits_getbits(audio->astream, 2); + } + +/* If we're in dual mono mode then get some extra info */ + if (bsi->acmod == 0) + { +/* Get the dialogue normalization level two */ + bsi->dialnorm2 = mpeg3bits_getbits(audio->astream, 5); + +/* Does compression gain two exist? */ + bsi->compr2e = mpeg3bits_getbits(audio->astream, 1); + if (bsi->compr2e) + { +/* Get compression gain two */ + bsi->compr2 = mpeg3bits_getbits(audio->astream, 8); + } + +/* Does language code two exist? */ + bsi->langcod2e = mpeg3bits_getbits(audio->astream, 1); + if (bsi->langcod2e) + { +/* Get langauge code two */ + bsi->langcod2 = mpeg3bits_getbits(audio->astream, 8); + } + +/* Does audio production info two exist? */ + bsi->audprodi2e = mpeg3bits_getbits(audio->astream, 1); + if (bsi->audprodi2e) + { +/* Get mix level two */ + bsi->mixlevel2 = mpeg3bits_getbits(audio->astream, 5); + +/* Get room type two */ + bsi->roomtyp2 = mpeg3bits_getbits(audio->astream, 2); + } + } + +/* Get the copyright bit */ + bsi->copyrightb = mpeg3bits_getbits(audio->astream, 1); + +/* Get the original bit */ + bsi->origbs = mpeg3bits_getbits(audio->astream, 1); + +/* Does timecode one exist? */ + bsi->timecod1e = mpeg3bits_getbits(audio->astream, 1); + + if(bsi->timecod1e) + bsi->timecod1 = mpeg3bits_getbits(audio->astream, 14); + +/* Does timecode two exist? */ + bsi->timecod2e = mpeg3bits_getbits(audio->astream, 1); + + if(bsi->timecod2e) + bsi->timecod2 = mpeg3bits_getbits(audio->astream, 14); + +/* Does addition info exist? */ + bsi->addbsie = mpeg3bits_getbits(audio->astream, 1); + + if(bsi->addbsie) + { +/* Get how much info is there */ + bsi->addbsil = mpeg3bits_getbits(audio->astream, 6); + +/* Get the additional info */ + for(i = 0; i < (bsi->addbsil + 1); i++) + bsi->addbsi[i] = mpeg3bits_getbits(audio->astream, 8); + } + + if(mpeg3bits_eof(audio->astream)) + { + mpeg3bits_use_demuxer(audio->astream); + return 1; + } +// return mpeg3bits_error(audio->astream); +} + +int mpeg3audio_read_ac3_audblk(mpeg3audio_t *audio) +{ + int i, j; + mpeg3_ac3bsi_t *bsi = &(audio->ac3_bsi); + mpeg3_ac3audblk_t *audblk = &(audio->ac3_audblk); + + for(i = 0; i < bsi->nfchans; i++) + { +/* Is this channel an interleaved 256 + 256 block ? */ + audblk->blksw[i] = mpeg3bits_getbits(audio->astream, 1); + } + + for(i = 0; i < bsi->nfchans; i++) + { +/* Should we dither this channel? */ + audblk->dithflag[i] = mpeg3bits_getbits(audio->astream, 1); + } + +/* Does dynamic range control exist? */ + audblk->dynrnge = mpeg3bits_getbits(audio->astream, 1); + if(audblk->dynrnge) + { +/* Get dynamic range info */ + audblk->dynrng = mpeg3bits_getbits(audio->astream, 8); + } + +/* If we're in dual mono mode then get the second channel DR info */ + if(bsi->acmod == 0) + { +/* Does dynamic range control two exist? */ + audblk->dynrng2e = mpeg3bits_getbits(audio->astream, 1); + if (audblk->dynrng2e) + { +/* Get dynamic range info */ + audblk->dynrng2 = mpeg3bits_getbits(audio->astream, 8); + } + } + +/* Does coupling strategy exist? */ + audblk->cplstre = mpeg3bits_getbits(audio->astream, 1); + if(audblk->cplstre) + { +/* Is coupling turned on? */ + audblk->cplinu = mpeg3bits_getbits(audio->astream, 1); + if(audblk->cplinu) + { + for(i = 0; i < bsi->nfchans; i++) + audblk->chincpl[i] = mpeg3bits_getbits(audio->astream, 1); + + if(bsi->acmod == 0x2) + audblk->phsflginu = mpeg3bits_getbits(audio->astream, 1); + + audblk->cplbegf = mpeg3bits_getbits(audio->astream, 4); + audblk->cplendf = mpeg3bits_getbits(audio->astream, 4); + audblk->ncplsubnd = (audblk->cplendf + 2) - audblk->cplbegf + 1; + +/* Calculate the start and end bins of the coupling channel */ + audblk->cplstrtmant = (audblk->cplbegf * 12) + 37 ; + audblk->cplendmant = ((audblk->cplendf + 3) * 12) + 37; + +/* The number of combined subbands is ncplsubnd minus each combined band */ + audblk->ncplbnd = audblk->ncplsubnd; + + for(i = 1; i < audblk->ncplsubnd; i++) + { + audblk->cplbndstrc[i] = mpeg3bits_getbits(audio->astream, 1); + audblk->ncplbnd -= audblk->cplbndstrc[i]; + } + } + } + + if(audblk->cplinu) + { +/* Loop through all the channels and get their coupling co-ords */ + for(i = 0; i < bsi->nfchans; i++) + { + if(!audblk->chincpl[i]) + continue; + +/* Is there new coupling co-ordinate info? */ + audblk->cplcoe[i] = mpeg3bits_getbits(audio->astream, 1); + + if(audblk->cplcoe[i]) + { + audblk->mstrcplco[i] = mpeg3bits_getbits(audio->astream, 2); + for(j = 0; j < audblk->ncplbnd; j++) + { + audblk->cplcoexp[i][j] = mpeg3bits_getbits(audio->astream, 4); + audblk->cplcomant[i][j] = mpeg3bits_getbits(audio->astream, 4); + } + } + } + +/* If we're in dual mono mode, there's going to be some phase info */ + if((bsi->acmod == 0x2) && audblk->phsflginu && + (audblk->cplcoe[0] || audblk->cplcoe[1])) + { + for(j = 0; j < audblk->ncplbnd; j++) + { + audblk->phsflg[j] = mpeg3bits_getbits(audio->astream, 1); + } + } + } + +/* If we're in dual mono mode, there may be a rematrix strategy */ + if(bsi->acmod == 0x2) + { + audblk->rematstr = mpeg3bits_getbits(audio->astream, 1); + if(audblk->rematstr) + { + if (audblk->cplinu == 0) + { + for(i = 0; i < 4; i++) + audblk->rematflg[i] = mpeg3bits_getbits(audio->astream, 1); + } + if((audblk->cplbegf > 2) && audblk->cplinu) + { + for(i = 0; i < 4; i++) + audblk->rematflg[i] = mpeg3bits_getbits(audio->astream, 1); + } + if((audblk->cplbegf <= 2) && audblk->cplinu) + { + for(i = 0; i < 3; i++) + audblk->rematflg[i] = mpeg3bits_getbits(audio->astream, 1); + } + if((audblk->cplbegf == 0) && audblk->cplinu) + for(i = 0; i < 2; i++) + audblk->rematflg[i] = mpeg3bits_getbits(audio->astream, 1); + + } + } + + if (audblk->cplinu) + { +/* Get the coupling channel exponent strategy */ + audblk->cplexpstr = mpeg3bits_getbits(audio->astream, 2); + + if(audblk->cplexpstr == 0) + audblk->ncplgrps = 0; + else + audblk->ncplgrps = (audblk->cplendmant - audblk->cplstrtmant) / + (3 << (audblk->cplexpstr - 1)); + + } + + for(i = 0; i < bsi->nfchans; i++) + { + audblk->chexpstr[i] = mpeg3bits_getbits(audio->astream, 2); + } + +/* Get the exponent strategy for lfe channel */ + if(bsi->lfeon) + audblk->lfeexpstr = mpeg3bits_getbits(audio->astream, 1); + +/* Determine the bandwidths of all the fbw channels */ + for(i = 0; i < bsi->nfchans; i++) + { + unsigned short grp_size; + + if(audblk->chexpstr[i] != MPEG3_EXP_REUSE) + { + if (audblk->cplinu && audblk->chincpl[i]) + { + audblk->endmant[i] = audblk->cplstrtmant; + } + else + { + audblk->chbwcod[i] = mpeg3bits_getbits(audio->astream, 6); + audblk->endmant[i] = ((audblk->chbwcod[i] + 12) * 3) + 37; + } + +/* Calculate the number of exponent groups to fetch */ + grp_size = 3 * (1 << (audblk->chexpstr[i] - 1)); + audblk->nchgrps[i] = (audblk->endmant[i] - 1 + (grp_size - 3)) / grp_size; + } + } + +/* Get the coupling exponents if they exist */ + if(audblk->cplinu && (audblk->cplexpstr != MPEG3_EXP_REUSE)) + { + audblk->cplabsexp = mpeg3bits_getbits(audio->astream, 4); + for(i = 0; i< audblk->ncplgrps; i++) + audblk->cplexps[i] = mpeg3bits_getbits(audio->astream, 7); + } + +/* Get the fwb channel exponents */ + for(i = 0; i < bsi->nfchans; i++) + { + if(audblk->chexpstr[i] != MPEG3_EXP_REUSE) + { + audblk->exps[i][0] = mpeg3bits_getbits(audio->astream, 4); + for(j = 1; j <= audblk->nchgrps[i]; j++) + audblk->exps[i][j] = mpeg3bits_getbits(audio->astream, 7); + audblk->gainrng[i] = mpeg3bits_getbits(audio->astream, 2); + } + } + +/* Get the lfe channel exponents */ + if(bsi->lfeon && (audblk->lfeexpstr != MPEG3_EXP_REUSE)) + { + audblk->lfeexps[0] = mpeg3bits_getbits(audio->astream, 4); + audblk->lfeexps[1] = mpeg3bits_getbits(audio->astream, 7); + audblk->lfeexps[2] = mpeg3bits_getbits(audio->astream, 7); + } + +/* Get the parametric bit allocation parameters */ + audblk->baie = mpeg3bits_getbits(audio->astream, 1); + + if(audblk->baie) + { + audblk->sdcycod = mpeg3bits_getbits(audio->astream, 2); + audblk->fdcycod = mpeg3bits_getbits(audio->astream, 2); + audblk->sgaincod = mpeg3bits_getbits(audio->astream, 2); + audblk->dbpbcod = mpeg3bits_getbits(audio->astream, 2); + audblk->floorcod = mpeg3bits_getbits(audio->astream, 3); + } + + +/* Get the SNR off set info if it exists */ + audblk->snroffste = mpeg3bits_getbits(audio->astream, 1); + + if(audblk->snroffste) + { + audblk->csnroffst = mpeg3bits_getbits(audio->astream, 6); + + if(audblk->cplinu) + { + audblk->cplfsnroffst = mpeg3bits_getbits(audio->astream, 4); + audblk->cplfgaincod = mpeg3bits_getbits(audio->astream, 3); + } + + for(i = 0; i < bsi->nfchans; i++) + { + audblk->fsnroffst[i] = mpeg3bits_getbits(audio->astream, 4); + audblk->fgaincod[i] = mpeg3bits_getbits(audio->astream, 3); + } + if(bsi->lfeon) + { + + audblk->lfefsnroffst = mpeg3bits_getbits(audio->astream, 4); + audblk->lfefgaincod = mpeg3bits_getbits(audio->astream, 3); + } + } + +/* Get coupling leakage info if it exists */ + if(audblk->cplinu) + { + audblk->cplleake = mpeg3bits_getbits(audio->astream, 1); + + if(audblk->cplleake) + { + audblk->cplfleak = mpeg3bits_getbits(audio->astream, 3); + audblk->cplsleak = mpeg3bits_getbits(audio->astream, 3); + } + } + +/* Get the delta bit alloaction info */ + audblk->deltbaie = mpeg3bits_getbits(audio->astream, 1); + + if(audblk->deltbaie) + { + if(audblk->cplinu) + audblk->cpldeltbae = mpeg3bits_getbits(audio->astream, 2); + + for(i = 0; i < bsi->nfchans; i++) + audblk->deltbae[i] = mpeg3bits_getbits(audio->astream, 2); + + if (audblk->cplinu && (audblk->cpldeltbae == DELTA_BIT_NEW)) + { + audblk->cpldeltnseg = mpeg3bits_getbits(audio->astream, 3); + for(i = 0; i < audblk->cpldeltnseg + 1; i++) + { + audblk->cpldeltoffst[i] = mpeg3bits_getbits(audio->astream, 5); + audblk->cpldeltlen[i] = mpeg3bits_getbits(audio->astream, 4); + audblk->cpldeltba[i] = mpeg3bits_getbits(audio->astream, 3); + } + } + + for(i = 0; i < bsi->nfchans; i++) + { + if (audblk->deltbae[i] == DELTA_BIT_NEW) + { + audblk->deltnseg[i] = mpeg3bits_getbits(audio->astream, 3); + for(j = 0; j < audblk->deltnseg[i] + 1; j++) + { + audblk->deltoffst[i][j] = mpeg3bits_getbits(audio->astream, 5); + audblk->deltlen[i][j] = mpeg3bits_getbits(audio->astream, 4); + audblk->deltba[i][j] = mpeg3bits_getbits(audio->astream, 3); + } + } + } + } + +/* Check to see if there's any dummy info to get */ + if((audblk->skiple = mpeg3bits_getbits(audio->astream, 1))) + { + unsigned int skip_data; + audblk->skipl = mpeg3bits_getbits(audio->astream, 9); + for(i = 0; i < audblk->skipl ; i++) + { + skip_data = mpeg3bits_getbits(audio->astream, 8); + } + } + + return mpeg3bits_error(audio->astream); +} + + +/* This routine simply does stereo rematrixing for the 2 channel + * stereo mode */ +int mpeg3audio_ac3_rematrix(mpeg3_ac3audblk_t *audblk, + mpeg3ac3_stream_samples_t samples) +{ + int num_bands; + int start; + int end; + int i, j; + mpeg3_real_t left, right; + + if(audblk->cplinu || audblk->cplbegf > 2) + num_bands = 4; + else if (audblk->cplbegf > 0) + num_bands = 3; + else + num_bands = 2; + + for(i = 0; i < num_bands; i++) + { + if(!audblk->rematflg[i]) + continue; + + start = mpeg3_rematrix_band[i].start; + end = mpeg3_min(mpeg3_rematrix_band[i].end, 12 * audblk->cplbegf + 36); + + for(j = start; j < end; j++) + { + left = samples[0][j] + samples[1][j]; + right = samples[0][j] - samples[1][j]; + samples[0][j] = left; + samples[1][j] = right; + } + } + return 0; +} + + +int mpeg3audio_ac3_reset_frame(mpeg3audio_t *audio) +{ + memset(&audio->ac3_bit_allocation, 0, sizeof(mpeg3_ac3_bitallocation_t)); + memset(&audio->ac3_mantissa, 0, sizeof(mpeg3_ac3_mantissa_t)); + memset(&audio->ac3_audblk, 0, sizeof(mpeg3_ac3audblk_t)); + + return 0; +} + +int mpeg3audio_do_ac3(mpeg3audio_t *audio) +{ + int result = 0, i; + +/* Reset the coefficients and exponents */ + mpeg3audio_ac3_reset_frame(audio); + + for(i = 0; i < 6 && !result; i++) + { + memset(audio->ac3_samples, 0, sizeof(mpeg3_real_t) * 256 * (audio->ac3_bsi.nfchans + audio->ac3_bsi.lfeon)); +/* Extract most of the audblk info from the bitstream + * (minus the mantissas */ + result |= mpeg3audio_read_ac3_audblk(audio); + +/* Take the differential exponent data and turn it into + * absolute exponents */ + if(!result) result |= mpeg3audio_ac3_exponent_unpack(audio, + &(audio->ac3_bsi), + &(audio->ac3_audblk)); + +/* Figure out how many bits per mantissa */ + if(!result) result |= mpeg3audio_ac3_bit_allocate(audio, + audio->sampling_frequency_code, + &(audio->ac3_bsi), + &(audio->ac3_audblk)); + +/* Extract the mantissas from the data stream */ + if(!result) result |= mpeg3audio_ac3_coeff_unpack(audio, + &(audio->ac3_bsi), + &(audio->ac3_audblk), + audio->ac3_samples); + + if(audio->ac3_bsi.acmod == 0x2) + if(!result) result |= mpeg3audio_ac3_rematrix(&(audio->ac3_audblk), + audio->ac3_samples); + +/* Convert the frequency data into time samples */ + if(!result) result |= mpeg3audio_ac3_imdct(audio, + &(audio->ac3_bsi), + &(audio->ac3_audblk), + audio->ac3_samples); + + if(audio->pcm_point / audio->channels >= audio->pcm_allocated - MPEG3AUDIO_PADDING * audio->channels) + { +/* Need more room */ + mpeg3audio_replace_buffer(audio, audio->pcm_allocated + MPEG3AUDIO_PADDING * audio->channels); + } + } + + mpeg3bits_use_demuxer(audio->astream); + + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/ac3.h b/core/multimedia/opieplayer/libmpeg3/audio/ac3.h new file mode 100644 index 0000000..9161c36 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/ac3.h @@ -0,0 +1,308 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef AC3_H +#define AC3_H + +#include "mpeg3real.h" + +#define MAX_AC3_FRAMESIZE 1920 * 2 + 512 + +extern int mpeg3_ac3_samplerates[3]; + +/* Exponent strategy constants */ +#define MPEG3_EXP_REUSE (0) +#define MPEG3_EXP_D15 (1) +#define MPEG3_EXP_D25 (2) +#define MPEG3_EXP_D45 (3) + +/* Delta bit allocation constants */ +#define DELTA_BIT_REUSE (0) +#define DELTA_BIT_NEW (1) +#define DELTA_BIT_NONE (2) +#define DELTA_BIT_RESERVED (3) + + +typedef mpeg3_real_t mpeg3ac3_stream_samples_t[6][256]; + +typedef struct +{ +/* Bit stream identification == 0x8 */ + int bsid; +/* Bit stream mode */ + int bsmod; +/* Audio coding mode */ + int acmod; +/* If we're using the centre channel then */ +/* centre mix level */ + int cmixlev; +/* If we're using the surround channel then */ +/* surround mix level */ + int surmixlev; +/* If we're in 2/0 mode then */ +/* Dolby surround mix level - NOT USED - */ + int dsurmod; +/* Low frequency effects on */ + int lfeon; +/* Dialogue Normalization level */ + int dialnorm; +/* Compression exists */ + int compre; +/* Compression level */ + int compr; +/* Language code exists */ + int langcode; +/* Language code */ + int langcod; +/* Audio production info exists*/ + unsigned int audprodie; + int mixlevel; + int roomtyp; +/* If we're in dual mono mode (acmod == 0) then extra stuff */ + int dialnorm2; + int compr2e; + int compr2; + int langcod2e; + int langcod2; + int audprodi2e; + int mixlevel2; + int roomtyp2; +/* Copyright bit */ + int copyrightb; +/* Original bit */ + int origbs; +/* Timecode 1 exists */ + int timecod1e; +/* Timecode 1 */ + unsigned int timecod1; +/* Timecode 2 exists */ + int timecod2e; +/* Timecode 2 */ + unsigned int timecod2; +/* Additional bit stream info exists */ + int addbsie; +/* Additional bit stream length - 1 (in bytes) */ + int addbsil; +/* Additional bit stream information (max 64 bytes) */ + unsigned char addbsi[64]; + +/* Information not in the AC-3 bitstream, but derived */ +/* Number of channels (excluding LFE) + * Derived from acmod */ + int nfchans; +} mpeg3_ac3bsi_t; + +typedef struct +{ +/* block switch bit indexed by channel num */ + unsigned short blksw[5]; +/* dither enable bit indexed by channel num */ + unsigned short dithflag[5]; +/* dynamic range gain exists */ + int dynrnge; +/* dynamic range gain */ + int dynrng; +/* if acmod==0 then */ +/* dynamic range 2 gain exists */ + int dynrng2e; +/* dynamic range 2 gain */ + int dynrng2; +/* coupling strategy exists */ + int cplstre; +/* coupling in use */ + int cplinu; +/* channel coupled */ + unsigned short chincpl[5]; +/* if acmod==2 then */ +/* Phase flags in use */ + int phsflginu; +/* coupling begin frequency code */ + int cplbegf; +/* coupling end frequency code */ + int cplendf; +/* coupling band structure bits */ + unsigned short cplbndstrc[18]; +/* Do coupling co-ords exist for this channel? */ + unsigned short cplcoe[5]; +/* Master coupling co-ordinate */ + unsigned short mstrcplco[5]; +/* Per coupling band coupling co-ordinates */ + unsigned short cplcoexp[5][18]; + unsigned short cplcomant[5][18]; +/* Phase flags for dual mono */ + unsigned short phsflg[18]; +/* Is there a rematrixing strategy */ + unsigned int rematstr; +/* Rematrixing bits */ + unsigned short rematflg[4]; +/* Coupling exponent strategy */ + int cplexpstr; +/* Exponent strategy for full bandwidth channels */ + unsigned short chexpstr[5]; +/* Exponent strategy for lfe channel */ + int lfeexpstr; +/* Channel bandwidth for independent channels */ + unsigned short chbwcod[5]; +/* The absolute coupling exponent */ + int cplabsexp; +/* Coupling channel exponents (D15 mode gives 18 * 12 /3 encoded exponents */ + unsigned short cplexps[18 * 12 / 3]; +/* fbw channel exponents */ + unsigned short exps[5][252 / 3]; +/* channel gain range */ + unsigned short gainrng[5]; +/* low frequency exponents */ + unsigned short lfeexps[3]; + +/* Bit allocation info */ + int baie; +/* Slow decay code */ + int sdcycod; +/* Fast decay code */ + int fdcycod; +/* Slow gain code */ + int sgaincod; +/* dB per bit code */ + int dbpbcod; +/* masking floor code */ + int floorcod; + +/* SNR offset info */ + int snroffste; +/* coarse SNR offset */ + int csnroffst; +/* coupling fine SNR offset */ + int cplfsnroffst; +/* coupling fast gain code */ + int cplfgaincod; +/* fbw fine SNR offset */ + unsigned short fsnroffst[5]; +/* fbw fast gain code */ + unsigned short fgaincod[5]; +/* lfe fine SNR offset */ + int lfefsnroffst; +/* lfe fast gain code */ + int lfefgaincod; + +/* Coupling leak info */ + int cplleake; +/* coupling fast leak initialization */ + int cplfleak; +/* coupling slow leak initialization */ + int cplsleak; + +/* delta bit allocation info */ + int deltbaie; +/* coupling delta bit allocation exists */ + int cpldeltbae; +/* fbw delta bit allocation exists */ + unsigned short deltbae[5]; +/* number of cpl delta bit segments */ + int cpldeltnseg; +/* coupling delta bit allocation offset */ + short cpldeltoffst[8]; +/* coupling delta bit allocation length */ + short cpldeltlen[8]; +/* coupling delta bit allocation length */ + short cpldeltba[8]; +/* number of delta bit segments */ + unsigned short deltnseg[5]; +/* fbw delta bit allocation offset */ + short deltoffst[5][8]; +/* fbw delta bit allocation length */ + short deltlen[5][8]; +/* fbw delta bit allocation length */ + short deltba[5][8]; + +/* skip length exists */ + int skiple; +/* skip length */ + int skipl; + +/* channel mantissas */ + short chmant[5][256]; + +/* coupling mantissas */ + unsigned short cplmant[256]; + +/* coupling mantissas */ + unsigned short lfemant[7]; + +/* -- Information not in the bitstream, but derived thereof -- */ + +/* Number of coupling sub-bands */ + int ncplsubnd; + +/* Number of combined coupling sub-bands + * Derived from ncplsubnd and cplbndstrc */ + int ncplbnd; + +/* Number of exponent groups by channel + * Derived from strmant, endmant */ + int nchgrps[5]; + +/* Number of coupling exponent groups + * Derived from cplbegf, cplendf, cplexpstr */ + int ncplgrps; + +/* End mantissa numbers of fbw channels */ + unsigned short endmant[5]; + +/* Start and end mantissa numbers for the coupling channel */ + int cplstrtmant; + int cplendmant; + +/* Decoded exponent info */ + unsigned short fbw_exp[5][256]; + unsigned short cpl_exp[256]; + unsigned short lfe_exp[7]; + +/* Bit allocation pointer results */ + short fbw_bap[5][256]; +/*FIXME figure out exactly how many entries there should be (253-37?) */ + short cpl_bap[256]; + short lfe_bap[7]; +} mpeg3_ac3audblk_t; + +/* Bit allocation data */ +typedef struct +{ + int sdecay; + int fdecay; + int sgain; + int dbknee; + int floor; + short psd[256]; + short bndpsd[256]; + short excite[256]; + short mask[256]; +} mpeg3_ac3_bitallocation_t; + +/* Mantissa data */ +typedef struct +{ + unsigned short m_1[3]; + unsigned short m_2[3]; + unsigned short m_4[2]; + unsigned short m_1_pointer; + unsigned short m_2_pointer; + unsigned short m_4_pointer; +} mpeg3_ac3_mantissa_t; + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/audio/bit_allocation.c b/core/multimedia/opieplayer/libmpeg3/audio/bit_allocation.c new file mode 100644 index 0000000..29df7d7 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/bit_allocation.c @@ -0,0 +1,586 @@ +/* + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * + * This file is part of libmpeg3 + * + * libmpeg3 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. + * + * libmpeg3 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. + * + */ + +#include "mpeg3audio.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include +#include + +/* Bit allocation tables */ + +static short mpeg3_slowdec[] = { 0x0f, 0x11, 0x13, 0x15 }; +static short mpeg3_fastdec[] = { 0x3f, 0x53, 0x67, 0x7b }; +static short mpeg3_slowgain[] = { 0x540, 0x4d8, 0x478, 0x410 }; +static short mpeg3_dbpbtab[] = { 0x000, 0x700, 0x900, 0xb00 }; + +static unsigned short mpeg3_floortab[] = { 0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800 }; +static short mpeg3_fastgain[] = { 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400 }; + + +static short mpeg3_bndtab[] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 31, + 34, 37, 40, 43, 46, 49, 55, 61, 67, 73, + 79, 85, 97, 109, 121, 133, 157, 181, 205, 229 +}; + +static short mpeg3_bndsz[] = +{ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, + 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, + 6, 12, 12, 12, 12, 24, 24, 24, 24, 24 +}; + +static short mpeg3_masktab[] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 29, + 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, + 34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 37, 37, 37, + 37, 37, 37, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 40, + 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0 +}; + + +static short mpeg3_latab[] = +{ + 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003b, 0x003a, 0x0039, + 0x0038, 0x0037, 0x0036, 0x0035, 0x0034, 0x0034, 0x0033, 0x0032, + 0x0031, 0x0030, 0x002f, 0x002f, 0x002e, 0x002d, 0x002c, 0x002c, + 0x002b, 0x002a, 0x0029, 0x0029, 0x0028, 0x0027, 0x0026, 0x0026, + 0x0025, 0x0024, 0x0024, 0x0023, 0x0023, 0x0022, 0x0021, 0x0021, + 0x0020, 0x0020, 0x001f, 0x001e, 0x001e, 0x001d, 0x001d, 0x001c, + 0x001c, 0x001b, 0x001b, 0x001a, 0x001a, 0x0019, 0x0019, 0x0018, + 0x0018, 0x0017, 0x0017, 0x0016, 0x0016, 0x0015, 0x0015, 0x0015, + 0x0014, 0x0014, 0x0013, 0x0013, 0x0013, 0x0012, 0x0012, 0x0012, + 0x0011, 0x0011, 0x0011, 0x0010, 0x0010, 0x0010, 0x000f, 0x000f, + 0x000f, 0x000e, 0x000e, 0x000e, 0x000d, 0x000d, 0x000d, 0x000d, + 0x000c, 0x000c, 0x000c, 0x000c, 0x000b, 0x000b, 0x000b, 0x000b, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0009, 0x0009, 0x0009, + 0x0009, 0x0009, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0005, 0x0005, + 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, + 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static short mpeg3_hth[][50] = +{ + { + 0x04d0, 0x04d0, 0x0440, 0x0400, 0x03e0, 0x03c0, 0x03b0, 0x03b0, + 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390, + 0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360, 0x0350, 0x0350, + 0x0340, 0x0340, 0x0330, 0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0, + 0x02f0, 0x02f0, 0x0300, 0x0310, 0x0340, 0x0390, 0x03e0, 0x0420, + 0x0460, 0x0490, 0x04a0, 0x0460, 0x0440, 0x0440, 0x0520, 0x0800, + 0x0840, 0x0840 + }, + + { + 0x04f0, 0x04f0, 0x0460, 0x0410, 0x03e0, 0x03d0, 0x03c0, 0x03b0, + 0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, + 0x0390, 0x0380, 0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360, + 0x0350, 0x0350, 0x0340, 0x0340, 0x0320, 0x0310, 0x0300, 0x02f0, + 0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0320, 0x0350, 0x0390, 0x03e0, + 0x0420, 0x0450, 0x04a0, 0x0490, 0x0460, 0x0440, 0x0480, 0x0630, + 0x0840, 0x0840 + }, + + { + 0x0580, 0x0580, 0x04b0, 0x0450, 0x0420, 0x03f0, 0x03e0, 0x03d0, + 0x03c0, 0x03b0, 0x03b0, 0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, + 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390, 0x0390, + 0x0380, 0x0380, 0x0380, 0x0370, 0x0360, 0x0350, 0x0340, 0x0330, + 0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0310, + 0x0330, 0x0350, 0x03c0, 0x0410, 0x0470, 0x04a0, 0x0460, 0x0440, + 0x0450, 0x04e0 + } +}; + + +static short mpeg3_baptab[] = +{ + 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, + 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, + 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15 +}; + + +inline int logadd(int a, int b) +{ + int c; + int address; + + c = a - b; + address = mpeg3_min((abs(c) >> 1), 255); + + if(c >= 0) + return(a + mpeg3_latab[address]); + else + return(b + mpeg3_latab[address]); +} + + +int mpeg3audio_ac3_calc_lowcomp(int a, int b0, int b1, int bin) +{ + if(bin < 7) + { + if((b0 + 256) == b1) + a = 384; + else + if(b0 > b1) + a = mpeg3_max(0, a - 64); + } + else if(bin < 20) + { + if((b0 + 256) == b1) + a = 320; + else if(b0 > b1) + a = mpeg3_max(0, a - 64) ; + } + else + a = mpeg3_max(0, a - 128); + + return(a); +} + +void mpeg3audio_ac3_ba_compute_psd(int start, + int end, + unsigned short exps[], + short psd[], + short bndpsd[]) +{ + int bin,i,j,k; + int lastbin = 0; + +/* Map the exponents into dBs */ + for (bin = start; bin < end; bin++) + { + psd[bin] = (3072 - (exps[bin] << 7)); + } + +/* Integrate the psd function over each bit allocation band */ + j = start; + k = mpeg3_masktab[start]; + + do + { + lastbin = mpeg3_min(mpeg3_bndtab[k] + mpeg3_bndsz[k], end); + bndpsd[k] = psd[j]; + j++; + + for(i = j; i < lastbin; i++) + { + bndpsd[k] = logadd(bndpsd[k], psd[j]); + j++; + } + + k++; + }while(end > lastbin); +} + +void mpeg3audio_ac3_ba_compute_excitation(mpeg3audio_t *audio, + int start, + int end, + int fgain, + int fastleak, + int slowleak, + int is_lfe, + short bndpsd[], + short excite[]) +{ + int bin; + int bndstrt; + int bndend; + int lowcomp = 0; + int begin = 0; + +/* Compute excitation function */ + bndstrt = mpeg3_masktab[start]; + bndend = mpeg3_masktab[end - 1] + 1; + + if(bndstrt == 0) /* For fbw and lfe channels */ + { + lowcomp = mpeg3audio_ac3_calc_lowcomp(lowcomp, bndpsd[0], bndpsd[1], 0); + excite[0] = bndpsd[0] - fgain - lowcomp; + lowcomp = mpeg3audio_ac3_calc_lowcomp(lowcomp, bndpsd[1], bndpsd[2], 1); + excite[1] = bndpsd[1] - fgain - lowcomp; + begin = 7 ; + +/* Note: Do not call mpeg3audio_ac3_calc_lowcomp() for the last band of the lfe channel, (bin = 6) */ + for (bin = 2; bin < 7; bin++) + { + if(!(is_lfe && (bin == 6))) + lowcomp = mpeg3audio_ac3_calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin); + fastleak = bndpsd[bin] - fgain; + slowleak = bndpsd[bin] - audio->ac3_bit_allocation.sgain; + excite[bin] = fastleak - lowcomp; + + if(!(is_lfe && (bin == 6))) + { + if(bndpsd[bin] <= bndpsd[bin+1]) + { + begin = bin + 1 ; + break; + } + } + } + + for (bin = begin; bin < mpeg3_min(bndend, 22); bin++) + { + if (!(is_lfe && (bin == 6))) + lowcomp = mpeg3audio_ac3_calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin); + fastleak -= audio->ac3_bit_allocation.fdecay; + fastleak = mpeg3_max(fastleak, bndpsd[bin] - fgain); + slowleak -= audio->ac3_bit_allocation.sdecay; + slowleak = mpeg3_max(slowleak, bndpsd[bin] - audio->ac3_bit_allocation.sgain); + excite[bin] = mpeg3_max(fastleak - lowcomp, slowleak); + } + begin = 22; + } + else /* For coupling channel */ + { + begin = bndstrt; + } + + for (bin = begin; bin < bndend; bin++) + { + fastleak -= audio->ac3_bit_allocation.fdecay; + fastleak = mpeg3_max(fastleak, bndpsd[bin] - fgain); + slowleak -= audio->ac3_bit_allocation.sdecay; + slowleak = mpeg3_max(slowleak, bndpsd[bin] - audio->ac3_bit_allocation.sgain); + excite[bin] = mpeg3_max(fastleak, slowleak) ; + } +} + +void mpeg3audio_ac3_ba_compute_mask(mpeg3audio_t *audio, + int start, + int end, + int fscod, + int deltbae, + int deltnseg, + short deltoffst[], + short deltba[], + short deltlen[], + short excite[], + short mask[]) +{ + int bin, k; + int bndstrt; + int bndend; + int delta; + + bndstrt = mpeg3_masktab[start]; + bndend = mpeg3_masktab[end - 1] + 1; + +/* Compute the masking curve */ + + for (bin = bndstrt; bin < bndend; bin++) + { + if (audio->ac3_bit_allocation.bndpsd[bin] < audio->ac3_bit_allocation.dbknee) + { + excite[bin] += ((audio->ac3_bit_allocation.dbknee - audio->ac3_bit_allocation.bndpsd[bin]) >> 2); + } + mask[bin] = mpeg3_max(excite[bin], mpeg3_hth[fscod][bin]); + } + +/* Perform delta bit modulation if necessary */ + if ((deltbae == DELTA_BIT_REUSE) || (deltbae == DELTA_BIT_NEW)) + { + int band = 0; + int seg = 0; + + for (seg = 0; seg < deltnseg + 1; seg++) + { + band += deltoffst[seg]; + if (deltba[seg] >= 4) + { + delta = (deltba[seg] - 3) << 7; + } + else + { + delta = (deltba[seg] - 4) << 7; + } + + for (k = 0; k < deltlen[seg]; k++) + { + mask[band] += delta; + band++; + } + } + } +} + +void mpeg3audio_ac3_ba_compute_bap(mpeg3audio_t *audio, + int start, + int end, + int snroffset, + short psd[], + short mask[], + short bap[]) +{ + int i, j, k; + short lastbin = 0; + short address = 0; + +/* Compute the bit allocation pointer for each bin */ + i = start; + j = mpeg3_masktab[start]; + + do + { + lastbin = mpeg3_min(mpeg3_bndtab[j] + mpeg3_bndsz[j], end); + mask[j] -= snroffset; + mask[j] -= audio->ac3_bit_allocation.floor; + + if(mask[j] < 0) + mask[j] = 0; + + mask[j] &= 0x1fe0; + mask[j] += audio->ac3_bit_allocation.floor; + for(k = i; k < lastbin; k++) + { + address = (psd[i] - mask[j]) >> 5; + address = mpeg3_min(63, mpeg3_max(0, address)); + bap[i] = mpeg3_baptab[address]; + i++; + } + j++; + }while (end > lastbin); +} + +int mpeg3audio_ac3_bit_allocate(mpeg3audio_t *audio, + unsigned int fscod, + mpeg3_ac3bsi_t *bsi, + mpeg3_ac3audblk_t *audblk) +{ + int result = 0; + int i; + int fgain; + int snroffset; + int start; + int end; + int fastleak; + int slowleak; + +/*printf("mpeg3audio_ac3_bit_allocate %d %d %d %d %d\n", audblk->sdcycod, audblk->fdcycod, audblk->sgaincod, audblk->dbpbcod, audblk->floorcod); */ +/* Only perform bit_allocation if the exponents have changed or we + * have new sideband information */ + if(audblk->chexpstr[0] == 0 && audblk->chexpstr[1] == 0 && + audblk->chexpstr[2] == 0 && audblk->chexpstr[3] == 0 && + audblk->chexpstr[4] == 0 && audblk->cplexpstr == 0 && + audblk->lfeexpstr == 0 && audblk->baie == 0 && + audblk->snroffste == 0 && audblk->deltbaie == 0) + return 0; + +/* Do some setup before we do the bit alloc */ + audio->ac3_bit_allocation.sdecay = mpeg3_slowdec[audblk->sdcycod]; + audio->ac3_bit_allocation.fdecay = mpeg3_fastdec[audblk->fdcycod]; + audio->ac3_bit_allocation.sgain = mpeg3_slowgain[audblk->sgaincod]; + audio->ac3_bit_allocation.dbknee = mpeg3_dbpbtab[audblk->dbpbcod]; + audio->ac3_bit_allocation.floor = mpeg3_floortab[audblk->floorcod]; + +/* if all the SNR offset constants are zero then the whole block is zero */ + if(!audblk->csnroffst && !audblk->fsnroffst[0] && + !audblk->fsnroffst[1] && !audblk->fsnroffst[2] && + !audblk->fsnroffst[3] && !audblk->fsnroffst[4] && + !audblk->cplfsnroffst && !audblk->lfefsnroffst) + { + memset(audblk->fbw_bap, 0, sizeof(short) * 256 * 5); + memset(audblk->cpl_bap, 0, sizeof(short) * 256); + memset(audblk->lfe_bap, 0, sizeof(short) * 7); + return 0; + } + + for(i = 0; i < bsi->nfchans; i++) + { + start = 0; + end = audblk->endmant[i]; + fgain = mpeg3_fastgain[audblk->fgaincod[i]]; + snroffset = (((audblk->csnroffst - 15) << 4) + audblk->fsnroffst[i]) << 2 ; + fastleak = 0; + slowleak = 0; + + mpeg3audio_ac3_ba_compute_psd(start, + end, + audblk->fbw_exp[i], + audio->ac3_bit_allocation.psd, + audio->ac3_bit_allocation.bndpsd); + + mpeg3audio_ac3_ba_compute_excitation(audio, + start, + end , + fgain, + fastleak, + slowleak, + 0, + audio->ac3_bit_allocation.bndpsd, + audio->ac3_bit_allocation.excite); + + mpeg3audio_ac3_ba_compute_mask(audio, + start, + end, + fscod, + audblk->deltbae[i], + audblk->deltnseg[i], + audblk->deltoffst[i], + audblk->deltba[i], + audblk->deltlen[i], + audio->ac3_bit_allocation.excite, + audio->ac3_bit_allocation.mask); + + mpeg3audio_ac3_ba_compute_bap(audio, + start, + end, + snroffset, + audio->ac3_bit_allocation.psd, + audio->ac3_bit_allocation.mask, + audblk->fbw_bap[i]); + } + + if(audblk->cplinu) + { + start = audblk->cplstrtmant; + end = audblk->cplendmant; + fgain = mpeg3_fastgain[audblk->cplfgaincod]; + snroffset = (((audblk->csnroffst - 15) << 4) + audblk->cplfsnroffst) << 2 ; + fastleak = (audblk->cplfleak << 8) + 768; + slowleak = (audblk->cplsleak << 8) + 768; + + mpeg3audio_ac3_ba_compute_psd(start, + end, + audblk->cpl_exp, + audio->ac3_bit_allocation.psd, + audio->ac3_bit_allocation.bndpsd); + + mpeg3audio_ac3_ba_compute_excitation(audio, + start, + end , + fgain, + fastleak, + slowleak, + 0, + audio->ac3_bit_allocation.bndpsd, + audio->ac3_bit_allocation.excite); + + mpeg3audio_ac3_ba_compute_mask(audio, + start, + end, + fscod, + audblk->cpldeltbae, + audblk->cpldeltnseg, + audblk->cpldeltoffst, + audblk->cpldeltba, + audblk->cpldeltlen, + audio->ac3_bit_allocation.excite, + audio->ac3_bit_allocation.mask); + + mpeg3audio_ac3_ba_compute_bap(audio, + start, + end, + snroffset, + audio->ac3_bit_allocation.psd, + audio->ac3_bit_allocation.mask, + audblk->cpl_bap); + } + + if(bsi->lfeon) + { + start = 0; + end = 7; + fgain = mpeg3_fastgain[audblk->lfefgaincod]; + snroffset = (((audblk->csnroffst - 15) << 4) + audblk->lfefsnroffst) << 2 ; + fastleak = 0; + slowleak = 0; + + mpeg3audio_ac3_ba_compute_psd(start, + end, + audblk->lfe_exp, + audio->ac3_bit_allocation.psd, + audio->ac3_bit_allocation.bndpsd); + + mpeg3audio_ac3_ba_compute_excitation(audio, + start, + end , + fgain, + fastleak, + slowleak, + 1, + audio->ac3_bit_allocation.bndpsd, + audio->ac3_bit_allocation.excite); + +/* Perform no delta bit allocation for lfe */ + mpeg3audio_ac3_ba_compute_mask(audio, + start, + end, + fscod, + 2, + 0, + 0, + 0, + 0, + audio->ac3_bit_allocation.excite, + audio->ac3_bit_allocation.mask); + + mpeg3audio_ac3_ba_compute_bap(audio, + start, + end, + snroffset, + audio->ac3_bit_allocation.psd, + audio->ac3_bit_allocation.mask, + audblk->lfe_bap); + } + + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/c_flags b/core/multimedia/opieplayer/libmpeg3/audio/c_flags new file mode 100755 index 0000000..d7943d0 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/c_flags @@ -0,0 +1 @@ +echo $CFLAGS diff --git a/core/multimedia/opieplayer/libmpeg3/audio/dct.c b/core/multimedia/opieplayer/libmpeg3/audio/dct.c new file mode 100644 index 0000000..1fd52ce --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/dct.c @@ -0,0 +1,1135 @@ +/* + * + * This file is part of libmpeg3 + * + * libmpeg3 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. + * + * libmpeg3 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. + * + */ + +/* + * Discrete Cosine Tansform (DCT) for subband synthesis + * optimized for machines with no auto-increment. + * The performance is highly compiler dependend. Maybe + * the dct64.c version for 'normal' processor may be faster + * even for Intel processors. + */ + +#include "mpeg3audio.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "tables.h" + +#include + +int mpeg3audio_dct64_1(mpeg3_real_t *out0, mpeg3_real_t *out1, mpeg3_real_t *b1, mpeg3_real_t *b2, mpeg3_real_t *samples) +{ + register mpeg3_real_t *costab = mpeg3_pnts[0]; + + b1[0x00] = samples[0x00] + samples[0x1F]; + b1[0x01] = samples[0x01] + samples[0x1E]; + b1[0x1F] = (samples[0x00] - samples[0x1F]) * costab[0x0]; + b1[0x1E] = (samples[0x01] - samples[0x1E]) * costab[0x1]; + + b1[0x02] = samples[0x02] + samples[0x1D]; + b1[0x03] = samples[0x03] + samples[0x1C]; + b1[0x1D] = (samples[0x02] - samples[0x1D]) * costab[0x2]; + b1[0x1C] = (samples[0x03] - samples[0x1C]) * costab[0x3]; + + b1[0x04] = samples[0x04] + samples[0x1B]; + b1[0x05] = samples[0x05] + samples[0x1A]; + b1[0x1B] = (samples[0x04] - samples[0x1B]) * costab[0x4]; + b1[0x1A] = (samples[0x05] - samples[0x1A]) * costab[0x5]; + + b1[0x06] = samples[0x06] + samples[0x19]; + b1[0x07] = samples[0x07] + samples[0x18]; + b1[0x19] = (samples[0x06] - samples[0x19]) * costab[0x6]; + b1[0x18] = (samples[0x07] - samples[0x18]) * costab[0x7]; + + b1[0x08] = samples[0x08] + samples[0x17]; + b1[0x09] = samples[0x09] + samples[0x16]; + b1[0x17] = (samples[0x08] - samples[0x17]) * costab[0x8]; + b1[0x16] = (samples[0x09] - samples[0x16]) * costab[0x9]; + + b1[0x0A] = samples[0x0A] + samples[0x15]; + b1[0x0B] = samples[0x0B] + samples[0x14]; + b1[0x15] = (samples[0x0A] - samples[0x15]) * costab[0xA]; + b1[0x14] = (samples[0x0B] - samples[0x14]) * costab[0xB]; + + b1[0x0C] = samples[0x0C] + samples[0x13]; + b1[0x0D] = samples[0x0D] + samples[0x12]; + b1[0x13] = (samples[0x0C] - samples[0x13]) * costab[0xC]; + b1[0x12] = (samples[0x0D] - samples[0x12]) * costab[0xD]; + + b1[0x0E] = samples[0x0E] + samples[0x11]; + b1[0x0F] = samples[0x0F] + samples[0x10]; + b1[0x11] = (samples[0x0E] - samples[0x11]) * costab[0xE]; + b1[0x10] = (samples[0x0F] - samples[0x10]) * costab[0xF]; + + costab = mpeg3_pnts[1]; + + b2[0x00] = b1[0x00] + b1[0x0F]; + b2[0x01] = b1[0x01] + b1[0x0E]; + b2[0x0F] = (b1[0x00] - b1[0x0F]) * costab[0]; + b2[0x0E] = (b1[0x01] - b1[0x0E]) * costab[1]; + + b2[0x02] = b1[0x02] + b1[0x0D]; + b2[0x03] = b1[0x03] + b1[0x0C]; + b2[0x0D] = (b1[0x02] - b1[0x0D]) * costab[2]; + b2[0x0C] = (b1[0x03] - b1[0x0C]) * costab[3]; + + b2[0x04] = b1[0x04] + b1[0x0B]; + b2[0x05] = b1[0x05] + b1[0x0A]; + b2[0x0B] = (b1[0x04] - b1[0x0B]) * costab[4]; + b2[0x0A] = (b1[0x05] - b1[0x0A]) * costab[5]; + + b2[0x06] = b1[0x06] + b1[0x09]; + b2[0x07] = b1[0x07] + b1[0x08]; + b2[0x09] = (b1[0x06] - b1[0x09]) * costab[6]; + b2[0x08] = (b1[0x07] - b1[0x08]) * costab[7]; + + /* */ + + b2[0x10] = b1[0x10] + b1[0x1F]; + b2[0x11] = b1[0x11] + b1[0x1E]; + b2[0x1F] = (b1[0x1F] - b1[0x10]) * costab[0]; + b2[0x1E] = (b1[0x1E] - b1[0x11]) * costab[1]; + + b2[0x12] = b1[0x12] + b1[0x1D]; + b2[0x13] = b1[0x13] + b1[0x1C]; + b2[0x1D] = (b1[0x1D] - b1[0x12]) * costab[2]; + b2[0x1C] = (b1[0x1C] - b1[0x13]) * costab[3]; + + b2[0x14] = b1[0x14] + b1[0x1B]; + b2[0x15] = b1[0x15] + b1[0x1A]; + b2[0x1B] = (b1[0x1B] - b1[0x14]) * costab[4]; + b2[0x1A] = (b1[0x1A] - b1[0x15]) * costab[5]; + + b2[0x16] = b1[0x16] + b1[0x19]; + b2[0x17] = b1[0x17] + b1[0x18]; + b2[0x19] = (b1[0x19] - b1[0x16]) * costab[6]; + b2[0x18] = (b1[0x18] - b1[0x17]) * costab[7]; + + costab = mpeg3_pnts[2]; + + b1[0x00] = b2[0x00] + b2[0x07]; + b1[0x07] = (b2[0x00] - b2[0x07]) * costab[0]; + b1[0x01] = b2[0x01] + b2[0x06]; + b1[0x06] = (b2[0x01] - b2[0x06]) * costab[1]; + b1[0x02] = b2[0x02] + b2[0x05]; + b1[0x05] = (b2[0x02] - b2[0x05]) * costab[2]; + b1[0x03] = b2[0x03] + b2[0x04]; + b1[0x04] = (b2[0x03] - b2[0x04]) * costab[3]; + + b1[0x08] = b2[0x08] + b2[0x0F]; + b1[0x0F] = (b2[0x0F] - b2[0x08]) * costab[0]; + b1[0x09] = b2[0x09] + b2[0x0E]; + b1[0x0E] = (b2[0x0E] - b2[0x09]) * costab[1]; + b1[0x0A] = b2[0x0A] + b2[0x0D]; + b1[0x0D] = (b2[0x0D] - b2[0x0A]) * costab[2]; + b1[0x0B] = b2[0x0B] + b2[0x0C]; + b1[0x0C] = (b2[0x0C] - b2[0x0B]) * costab[3]; + + b1[0x10] = b2[0x10] + b2[0x17]; + b1[0x17] = (b2[0x10] - b2[0x17]) * costab[0]; + b1[0x11] = b2[0x11] + b2[0x16]; + b1[0x16] = (b2[0x11] - b2[0x16]) * costab[1]; + b1[0x12] = b2[0x12] + b2[0x15]; + b1[0x15] = (b2[0x12] - b2[0x15]) * costab[2]; + b1[0x13] = b2[0x13] + b2[0x14]; + b1[0x14] = (b2[0x13] - b2[0x14]) * costab[3]; + + b1[0x18] = b2[0x18] + b2[0x1F]; + b1[0x1F] = (b2[0x1F] - b2[0x18]) * costab[0]; + b1[0x19] = b2[0x19] + b2[0x1E]; + b1[0x1E] = (b2[0x1E] - b2[0x19]) * costab[1]; + b1[0x1A] = b2[0x1A] + b2[0x1D]; + b1[0x1D] = (b2[0x1D] - b2[0x1A]) * costab[2]; + b1[0x1B] = b2[0x1B] + b2[0x1C]; + b1[0x1C] = (b2[0x1C] - b2[0x1B]) * costab[3]; + + { + register mpeg3_real_t const cos0 = mpeg3_pnts[3][0]; + register mpeg3_real_t const cos1 = mpeg3_pnts[3][1]; + + b2[0x00] = b1[0x00] + b1[0x03]; + b2[0x03] = (b1[0x00] - b1[0x03]) * cos0; + b2[0x01] = b1[0x01] + b1[0x02]; + b2[0x02] = (b1[0x01] - b1[0x02]) * cos1; + + b2[0x04] = b1[0x04] + b1[0x07]; + b2[0x07] = (b1[0x07] - b1[0x04]) * cos0; + b2[0x05] = b1[0x05] + b1[0x06]; + b2[0x06] = (b1[0x06] - b1[0x05]) * cos1; + + b2[0x08] = b1[0x08] + b1[0x0B]; + b2[0x0B] = (b1[0x08] - b1[0x0B]) * cos0; + b2[0x09] = b1[0x09] + b1[0x0A]; + b2[0x0A] = (b1[0x09] - b1[0x0A]) * cos1; + + b2[0x0C] = b1[0x0C] + b1[0x0F]; + b2[0x0F] = (b1[0x0F] - b1[0x0C]) * cos0; + b2[0x0D] = b1[0x0D] + b1[0x0E]; + b2[0x0E] = (b1[0x0E] - b1[0x0D]) * cos1; + + b2[0x10] = b1[0x10] + b1[0x13]; + b2[0x13] = (b1[0x10] - b1[0x13]) * cos0; + b2[0x11] = b1[0x11] + b1[0x12]; + b2[0x12] = (b1[0x11] - b1[0x12]) * cos1; + + b2[0x14] = b1[0x14] + b1[0x17]; + b2[0x17] = (b1[0x17] - b1[0x14]) * cos0; + b2[0x15] = b1[0x15] + b1[0x16]; + b2[0x16] = (b1[0x16] - b1[0x15]) * cos1; + + b2[0x18] = b1[0x18] + b1[0x1B]; + b2[0x1B] = (b1[0x18] - b1[0x1B]) * cos0; + b2[0x19] = b1[0x19] + b1[0x1A]; + b2[0x1A] = (b1[0x19] - b1[0x1A]) * cos1; + + b2[0x1C] = b1[0x1C] + b1[0x1F]; + b2[0x1F] = (b1[0x1F] - b1[0x1C]) * cos0; + b2[0x1D] = b1[0x1D] + b1[0x1E]; + b2[0x1E] = (b1[0x1E] - b1[0x1D]) * cos1; + } + + { + register mpeg3_real_t const cos0 = mpeg3_pnts[4][0]; + + b1[0x00] = b2[0x00] + b2[0x01]; + b1[0x01] = (b2[0x00] - b2[0x01]) * cos0; + b1[0x02] = b2[0x02] + b2[0x03]; + b1[0x03] = (b2[0x03] - b2[0x02]) * cos0; + b1[0x02] += b1[0x03]; + + b1[0x04] = b2[0x04] + b2[0x05]; + b1[0x05] = (b2[0x04] - b2[0x05]) * cos0; + b1[0x06] = b2[0x06] + b2[0x07]; + b1[0x07] = (b2[0x07] - b2[0x06]) * cos0; + b1[0x06] += b1[0x07]; + b1[0x04] += b1[0x06]; + b1[0x06] += b1[0x05]; + b1[0x05] += b1[0x07]; + + b1[0x08] = b2[0x08] + b2[0x09]; + b1[0x09] = (b2[0x08] - b2[0x09]) * cos0; + b1[0x0A] = b2[0x0A] + b2[0x0B]; + b1[0x0B] = (b2[0x0B] - b2[0x0A]) * cos0; + b1[0x0A] += b1[0x0B]; + + b1[0x0C] = b2[0x0C] + b2[0x0D]; + b1[0x0D] = (b2[0x0C] - b2[0x0D]) * cos0; + b1[0x0E] = b2[0x0E] + b2[0x0F]; + b1[0x0F] = (b2[0x0F] - b2[0x0E]) * cos0; + b1[0x0E] += b1[0x0F]; + b1[0x0C] += b1[0x0E]; + b1[0x0E] += b1[0x0D]; + b1[0x0D] += b1[0x0F]; + + b1[0x10] = b2[0x10] + b2[0x11]; + b1[0x11] = (b2[0x10] - b2[0x11]) * cos0; + b1[0x12] = b2[0x12] + b2[0x13]; + b1[0x13] = (b2[0x13] - b2[0x12]) * cos0; + b1[0x12] += b1[0x13]; + + b1[0x14] = b2[0x14] + b2[0x15]; + b1[0x15] = (b2[0x14] - b2[0x15]) * cos0; + b1[0x16] = b2[0x16] + b2[0x17]; + b1[0x17] = (b2[0x17] - b2[0x16]) * cos0; + b1[0x16] += b1[0x17]; + b1[0x14] += b1[0x16]; + b1[0x16] += b1[0x15]; + b1[0x15] += b1[0x17]; + + b1[0x18] = b2[0x18] + b2[0x19]; + b1[0x19] = (b2[0x18] - b2[0x19]) * cos0; + b1[0x1A] = b2[0x1A] + b2[0x1B]; + b1[0x1B] = (b2[0x1B] - b2[0x1A]) * cos0; + b1[0x1A] += b1[0x1B]; + + b1[0x1C] = b2[0x1C] + b2[0x1D]; + b1[0x1D] = (b2[0x1C] - b2[0x1D]) * cos0; + b1[0x1E] = b2[0x1E] + b2[0x1F]; + b1[0x1F] = (b2[0x1F] - b2[0x1E]) * cos0; + b1[0x1E] += b1[0x1F]; + b1[0x1C] += b1[0x1E]; + b1[0x1E] += b1[0x1D]; + b1[0x1D] += b1[0x1F]; + } + + out0[0x10*16] = b1[0x00]; + out0[0x10*12] = b1[0x04]; + out0[0x10* 8] = b1[0x02]; + out0[0x10* 4] = b1[0x06]; + out0[0x10* 0] = b1[0x01]; + out1[0x10* 0] = b1[0x01]; + out1[0x10* 4] = b1[0x05]; + out1[0x10* 8] = b1[0x03]; + out1[0x10*12] = b1[0x07]; + + out0[0x10*14] = b1[0x08] + b1[0x0C]; + out0[0x10*10] = b1[0x0C] + b1[0x0a]; + out0[0x10* 6] = b1[0x0A] + b1[0x0E]; + out0[0x10* 2] = b1[0x0E] + b1[0x09]; + out1[0x10* 2] = b1[0x09] + b1[0x0D]; + out1[0x10* 6] = b1[0x0D] + b1[0x0B]; + out1[0x10*10] = b1[0x0B] + b1[0x0F]; + out1[0x10*14] = b1[0x0F]; + + { + register mpeg3_real_t tmp; + tmp = b1[0x18] + b1[0x1C]; + out0[0x10*15] = tmp + b1[0x10]; + out0[0x10*13] = tmp + b1[0x14]; + tmp = b1[0x1C] + b1[0x1A]; + out0[0x10*11] = tmp + b1[0x14]; + out0[0x10* 9] = tmp + b1[0x12]; + tmp = b1[0x1A] + b1[0x1E]; + out0[0x10* 7] = tmp + b1[0x12]; + out0[0x10* 5] = tmp + b1[0x16]; + tmp = b1[0x1E] + b1[0x19]; + out0[0x10* 3] = tmp + b1[0x16]; + out0[0x10* 1] = tmp + b1[0x11]; + tmp = b1[0x19] + b1[0x1D]; + out1[0x10* 1] = tmp + b1[0x11]; + out1[0x10* 3] = tmp + b1[0x15]; + tmp = b1[0x1D] + b1[0x1B]; + out1[0x10* 5] = tmp + b1[0x15]; + out1[0x10* 7] = tmp + b1[0x13]; + tmp = b1[0x1B] + b1[0x1F]; + out1[0x10* 9] = tmp + b1[0x13]; + out1[0x10*11] = tmp + b1[0x17]; + out1[0x10*13] = b1[0x17] + b1[0x1F]; + out1[0x10*15] = b1[0x1F]; + } + return 0; +} + +/* + * the call via dct64 is a trick to force GCC to use + * (new) registers for the b1,b2 pointer to the bufs[xx] field + */ +int mpeg3audio_dct64(mpeg3_real_t *a, mpeg3_real_t *b, mpeg3_real_t *c) +{ + mpeg3_real_t bufs[0x40]; + return mpeg3audio_dct64_1(a, b, bufs, bufs + 0x20, c); +} + +/*//////////////////////////////////////////////////////////////// */ +/* */ +/* 9 Point Inverse Discrete Cosine Transform */ +/* */ +/* This piece of code is Copyright 1997 Mikko Tommila and is freely usable */ +/* by anybody. The algorithm itself is of course in the public domain. */ +/* */ +/* Again derived heuristically from the 9-point WFTA. */ +/* */ +/* The algorithm is optimized (?) for speed, not for small rounding errors or */ +/* good readability. */ +/* */ +/* 36 additions, 11 multiplications */ +/* */ +/* Again this is very likely sub-optimal. */ +/* */ +/* The code is optimized to use a minimum number of temporary variables, */ +/* so it should compile quite well even on 8-register Intel x86 processors. */ +/* This makes the code quite obfuscated and very difficult to understand. */ +/* */ +/* References: */ +/* [1] S. Winograd: "On Computing the Discrete Fourier Transform", */ +/* Mathematics of Computation, Volume 32, Number 141, January 1978, */ +/* Pages 175-199 */ + + +/*------------------------------------------------------------------*/ +/* */ +/* Function: Calculation of the inverse MDCT */ +/* */ +/*------------------------------------------------------------------*/ + +int mpeg3audio_dct36(mpeg3_real_t *inbuf, mpeg3_real_t *o1, mpeg3_real_t *o2, mpeg3_real_t *wintab, mpeg3_real_t *tsbuf) +{ + mpeg3_real_t tmp[18]; + + { + register mpeg3_real_t *in = inbuf; + + in[17]+=in[16]; in[16]+=in[15]; in[15]+=in[14]; + in[14]+=in[13]; in[13]+=in[12]; in[12]+=in[11]; + in[11]+=in[10]; in[10]+=in[9]; in[9] +=in[8]; + in[8] +=in[7]; in[7] +=in[6]; in[6] +=in[5]; + in[5] +=in[4]; in[4] +=in[3]; in[3] +=in[2]; + in[2] +=in[1]; in[1] +=in[0]; + + in[17]+=in[15]; in[15]+=in[13]; in[13]+=in[11]; in[11]+=in[9]; + in[9] +=in[7]; in[7] +=in[5]; in[5] +=in[3]; in[3] +=in[1]; + + + { + mpeg3_real_t t3; + { + mpeg3_real_t t0, t1, t2; + + t0 = mpeg3_COS6_2 * (in[8] + in[16] - in[4]); + t1 = mpeg3_COS6_2 * in[12]; + + t3 = in[0]; + t2 = t3 - t1 - t1; + tmp[1] = tmp[7] = t2 - t0; + tmp[4] = t2 + t0 + t0; + t3 += t1; + + t2 = mpeg3_COS6_1 * (in[10] + in[14] - in[2]); + tmp[1] -= t2; + tmp[7] += t2; + } + { + mpeg3_real_t t0, t1, t2; + + t0 = mpeg3_cos9[0] * (in[4] + in[8] ); + t1 = mpeg3_cos9[1] * (in[8] - in[16]); + t2 = mpeg3_cos9[2] * (in[4] + in[16]); + + tmp[2] = tmp[6] = t3 - t0 - t2; + tmp[0] = tmp[8] = t3 + t0 + t1; + tmp[3] = tmp[5] = t3 - t1 + t2; + } + } + { + mpeg3_real_t t1, t2, t3; + + t1 = mpeg3_cos18[0] * (in[2] + in[10]); + t2 = mpeg3_cos18[1] * (in[10] - in[14]); + t3 = mpeg3_COS6_1 * in[6]; + + { + mpeg3_real_t t0 = t1 + t2 + t3; + tmp[0] += t0; + tmp[8] -= t0; + } + + t2 -= t3; + t1 -= t3; + + t3 = mpeg3_cos18[2] * (in[2] + in[14]); + + t1 += t3; + tmp[3] += t1; + tmp[5] -= t1; + + t2 -= t3; + tmp[2] += t2; + tmp[6] -= t2; + } + + + { + mpeg3_real_t t0, t1, t2, t3, t4, t5, t6, t7; + + t1 = mpeg3_COS6_2 * in[13]; + t2 = mpeg3_COS6_2 * (in[9] + in[17] - in[5]); + + t3 = in[1] + t1; + t4 = in[1] - t1 - t1; + t5 = t4 - t2; + + t0 = mpeg3_cos9[0] * (in[5] + in[9]); + t1 = mpeg3_cos9[1] * (in[9] - in[17]); + + tmp[13] = (t4 + t2 + t2) * mpeg3_tfcos36[17-13]; + t2 = mpeg3_cos9[2] * (in[5] + in[17]); + + t6 = t3 - t0 - t2; + t0 += t3 + t1; + t3 += t2 - t1; + + t2 = mpeg3_cos18[0] * (in[3] + in[11]); + t4 = mpeg3_cos18[1] * (in[11] - in[15]); + t7 = mpeg3_COS6_1 * in[7]; + + t1 = t2 + t4 + t7; + tmp[17] = (t0 + t1) * mpeg3_tfcos36[17-17]; + tmp[9] = (t0 - t1) * mpeg3_tfcos36[17-9]; + t1 = mpeg3_cos18[2] * (in[3] + in[15]); + t2 += t1 - t7; + + tmp[14] = (t3 + t2) * mpeg3_tfcos36[17-14]; + t0 = mpeg3_COS6_1 * (in[11] + in[15] - in[3]); + tmp[12] = (t3 - t2) * mpeg3_tfcos36[17-12]; + + t4 -= t1 + t7; + + tmp[16] = (t5 - t0) * mpeg3_tfcos36[17-16]; + tmp[10] = (t5 + t0) * mpeg3_tfcos36[17-10]; + tmp[15] = (t6 + t4) * mpeg3_tfcos36[17-15]; + tmp[11] = (t6 - t4) * mpeg3_tfcos36[17-11]; + } + +#define MACRO(v) \ + { \ + mpeg3_real_t tmpval; \ + tmpval = tmp[(v)] + tmp[17-(v)]; \ + out2[9+(v)] = tmpval * w[27+(v)]; \ + out2[8-(v)] = tmpval * w[26-(v)]; \ + tmpval = tmp[(v)] - tmp[17-(v)]; \ + ts[SBLIMIT*(8-(v))] = out1[8-(v)] + tmpval * w[8-(v)]; \ + ts[SBLIMIT*(9+(v))] = out1[9+(v)] + tmpval * w[9+(v)]; \ + } + + { + register mpeg3_real_t *out2 = o2; + register mpeg3_real_t *w = wintab; + register mpeg3_real_t *out1 = o1; + register mpeg3_real_t *ts = tsbuf; + + MACRO(0); + MACRO(1); + MACRO(2); + MACRO(3); + MACRO(4); + MACRO(5); + MACRO(6); + MACRO(7); + MACRO(8); + } + } + return 0; +} + +/* + * new DCT12 + */ +int mpeg3audio_dct12(mpeg3_real_t *in,mpeg3_real_t *rawout1,mpeg3_real_t *rawout2,register mpeg3_real_t *wi,register mpeg3_real_t *ts) +{ +#define DCT12_PART1 \ + in5 = in[5*3]; \ + in5 += (in4 = in[4*3]); \ + in4 += (in3 = in[3*3]); \ + in3 += (in2 = in[2*3]); \ + in2 += (in1 = in[1*3]); \ + in1 += (in0 = in[0*3]); \ + \ + in5 += in3; in3 += in1; \ + \ + in2 *= mpeg3_COS6_1; \ + in3 *= mpeg3_COS6_1; \ + +#define DCT12_PART2 \ + in0 += in4 * mpeg3_COS6_2; \ + \ + in4 = in0 + in2; \ + in0 -= in2; \ + \ + in1 += in5 * mpeg3_COS6_2; \ + \ + in5 = (in1 + in3) * mpeg3_tfcos12[0]; \ + in1 = (in1 - in3) * mpeg3_tfcos12[2]; \ + \ + in3 = in4 + in5; \ + in4 -= in5; \ + \ + in2 = in0 + in1; \ + in0 -= in1; + + + { + mpeg3_real_t in0,in1,in2,in3,in4,in5; + register mpeg3_real_t *out1 = rawout1; + ts[SBLIMIT*0] = out1[0]; ts[SBLIMIT*1] = out1[1]; ts[SBLIMIT*2] = out1[2]; + ts[SBLIMIT*3] = out1[3]; ts[SBLIMIT*4] = out1[4]; ts[SBLIMIT*5] = out1[5]; + + DCT12_PART1 + + { + mpeg3_real_t tmp0,tmp1 = (in0 - in4); + { + mpeg3_real_t tmp2 = (in1 - in5) * mpeg3_tfcos12[1]; + tmp0 = tmp1 + tmp2; + tmp1 -= tmp2; + } + ts[(17-1)*SBLIMIT] = out1[17-1] + tmp0 * wi[11-1]; + ts[(12+1)*SBLIMIT] = out1[12+1] + tmp0 * wi[6+1]; + ts[(6 +1)*SBLIMIT] = out1[6 +1] + tmp1 * wi[1]; + ts[(11-1)*SBLIMIT] = out1[11-1] + tmp1 * wi[5-1]; + } + + DCT12_PART2 + + ts[(17-0)*SBLIMIT] = out1[17-0] + in2 * wi[11-0]; + ts[(12+0)*SBLIMIT] = out1[12+0] + in2 * wi[6+0]; + ts[(12+2)*SBLIMIT] = out1[12+2] + in3 * wi[6+2]; + ts[(17-2)*SBLIMIT] = out1[17-2] + in3 * wi[11-2]; + + ts[(6+0)*SBLIMIT] = out1[6+0] + in0 * wi[0]; + ts[(11-0)*SBLIMIT] = out1[11-0] + in0 * wi[5-0]; + ts[(6+2)*SBLIMIT] = out1[6+2] + in4 * wi[2]; + ts[(11-2)*SBLIMIT] = out1[11-2] + in4 * wi[5-2]; + } + + in++; + + { + mpeg3_real_t in0,in1,in2,in3,in4,in5; + register mpeg3_real_t *out2 = rawout2; + + DCT12_PART1 + + { + mpeg3_real_t tmp0,tmp1 = (in0 - in4); + { + mpeg3_real_t tmp2 = (in1 - in5) * mpeg3_tfcos12[1]; + tmp0 = tmp1 + tmp2; + tmp1 -= tmp2; + } + out2[5-1] = tmp0 * wi[11-1]; + out2[0+1] = tmp0 * wi[6+1]; + ts[(12+1)*SBLIMIT] += tmp1 * wi[1]; + ts[(17-1)*SBLIMIT] += tmp1 * wi[5-1]; + } + + DCT12_PART2 + + out2[5-0] = in2 * wi[11-0]; + out2[0+0] = in2 * wi[6+0]; + out2[0+2] = in3 * wi[6+2]; + out2[5-2] = in3 * wi[11-2]; + + ts[(12+0)*SBLIMIT] += in0 * wi[0]; + ts[(17-0)*SBLIMIT] += in0 * wi[5-0]; + ts[(12+2)*SBLIMIT] += in4 * wi[2]; + ts[(17-2)*SBLIMIT] += in4 * wi[5-2]; + } + + in++; + + { + mpeg3_real_t in0,in1,in2,in3,in4,in5; + register mpeg3_real_t *out2 = rawout2; + out2[12]=out2[13]=out2[14]=out2[15]=out2[16]=out2[17]=0.0; + + DCT12_PART1 + + { + mpeg3_real_t tmp0,tmp1 = (in0 - in4); + { + mpeg3_real_t tmp2 = (in1 - in5) * mpeg3_tfcos12[1]; + tmp0 = tmp1 + tmp2; + tmp1 -= tmp2; + } + out2[11-1] = tmp0 * wi[11-1]; + out2[6 +1] = tmp0 * wi[6+1]; + out2[0+1] += tmp1 * wi[1]; + out2[5-1] += tmp1 * wi[5-1]; + } + + DCT12_PART2 + + out2[11-0] = in2 * wi[11-0]; + out2[6 +0] = in2 * wi[6+0]; + out2[6 +2] = in3 * wi[6+2]; + out2[11-2] = in3 * wi[11-2]; + + out2[0+0] += in0 * wi[0]; + out2[5-0] += in0 * wi[5-0]; + out2[0+2] += in4 * wi[2]; + out2[5-2] += in4 * wi[5-2]; + } + return 0; +} + +/* AC3 IMDCT tables */ + +/* Twiddle factors for IMDCT */ +#if !defined(USE_FIXED_POINT) || defined(PRINT_FIXED_POINT_TABLES) +static mpeg3_real_t mpeg3_xcos1[AC3_N / 4]; +static mpeg3_real_t mpeg3_xsin1[AC3_N / 4]; +static mpeg3_real_t mpeg3_xcos2[AC3_N / 8]; +static mpeg3_real_t mpeg3_xsin2[AC3_N / 8]; +#else +#define USE_FP_TABLES +#include "fptables.h" +#endif + +/* 128 point bit-reverse LUT */ +static unsigned char mpeg3_bit_reverse_512[] = +{ + 0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70, + 0x08, 0x48, 0x28, 0x68, 0x18, 0x58, 0x38, 0x78, + 0x04, 0x44, 0x24, 0x64, 0x14, 0x54, 0x34, 0x74, + 0x0c, 0x4c, 0x2c, 0x6c, 0x1c, 0x5c, 0x3c, 0x7c, + 0x02, 0x42, 0x22, 0x62, 0x12, 0x52, 0x32, 0x72, + 0x0a, 0x4a, 0x2a, 0x6a, 0x1a, 0x5a, 0x3a, 0x7a, + 0x06, 0x46, 0x26, 0x66, 0x16, 0x56, 0x36, 0x76, + 0x0e, 0x4e, 0x2e, 0x6e, 0x1e, 0x5e, 0x3e, 0x7e, + 0x01, 0x41, 0x21, 0x61, 0x11, 0x51, 0x31, 0x71, + 0x09, 0x49, 0x29, 0x69, 0x19, 0x59, 0x39, 0x79, + 0x05, 0x45, 0x25, 0x65, 0x15, 0x55, 0x35, 0x75, + 0x0d, 0x4d, 0x2d, 0x6d, 0x1d, 0x5d, 0x3d, 0x7d, + 0x03, 0x43, 0x23, 0x63, 0x13, 0x53, 0x33, 0x73, + 0x0b, 0x4b, 0x2b, 0x6b, 0x1b, 0x5b, 0x3b, 0x7b, + 0x07, 0x47, 0x27, 0x67, 0x17, 0x57, 0x37, 0x77, + 0x0f, 0x4f, 0x2f, 0x6f, 0x1f, 0x5f, 0x3f, 0x7f +}; + +static unsigned char mpeg3_bit_reverse_256[] = +{ + 0x00, 0x20, 0x10, 0x30, 0x08, 0x28, 0x18, 0x38, + 0x04, 0x24, 0x14, 0x34, 0x0c, 0x2c, 0x1c, 0x3c, + 0x02, 0x22, 0x12, 0x32, 0x0a, 0x2a, 0x1a, 0x3a, + 0x06, 0x26, 0x16, 0x36, 0x0e, 0x2e, 0x1e, 0x3e, + 0x01, 0x21, 0x11, 0x31, 0x09, 0x29, 0x19, 0x39, + 0x05, 0x25, 0x15, 0x35, 0x0d, 0x2d, 0x1d, 0x3d, + 0x03, 0x23, 0x13, 0x33, 0x0b, 0x2b, 0x1b, 0x3b, + 0x07, 0x27, 0x17, 0x37, 0x0f, 0x2f, 0x1f, 0x3f +}; + +/* Windowing function for Modified DCT - Thank you acroread */ +static mpeg3_real_t mpeg3_window[] = +{ + 0.00014, 0.00024, 0.00037, 0.00051, 0.00067, 0.00086, 0.00107, 0.00130, + 0.00157, 0.00187, 0.00220, 0.00256, 0.00297, 0.00341, 0.00390, 0.00443, + 0.00501, 0.00564, 0.00632, 0.00706, 0.00785, 0.00871, 0.00962, 0.01061, + 0.01166, 0.01279, 0.01399, 0.01526, 0.01662, 0.01806, 0.01959, 0.02121, + 0.02292, 0.02472, 0.02662, 0.02863, 0.03073, 0.03294, 0.03527, 0.03770, + 0.04025, 0.04292, 0.04571, 0.04862, 0.05165, 0.05481, 0.05810, 0.06153, + 0.06508, 0.06878, 0.07261, 0.07658, 0.08069, 0.08495, 0.08935, 0.09389, + 0.09859, 0.10343, 0.10842, 0.11356, 0.11885, 0.12429, 0.12988, 0.13563, + 0.14152, 0.14757, 0.15376, 0.16011, 0.16661, 0.17325, 0.18005, 0.18699, + 0.19407, 0.20130, 0.20867, 0.21618, 0.22382, 0.23161, 0.23952, 0.24757, + 0.25574, 0.26404, 0.27246, 0.28100, 0.28965, 0.29841, 0.30729, 0.31626, + 0.32533, 0.33450, 0.34376, 0.35311, 0.36253, 0.37204, 0.38161, 0.39126, + 0.40096, 0.41072, 0.42054, 0.43040, 0.44030, 0.45023, 0.46020, 0.47019, + 0.48020, 0.49022, 0.50025, 0.51028, 0.52031, 0.53033, 0.54033, 0.55031, + 0.56026, 0.57019, 0.58007, 0.58991, 0.59970, 0.60944, 0.61912, 0.62873, + 0.63827, 0.64774, 0.65713, 0.66643, 0.67564, 0.68476, 0.69377, 0.70269, + 0.71150, 0.72019, 0.72877, 0.73723, 0.74557, 0.75378, 0.76186, 0.76981, + 0.77762, 0.78530, 0.79283, 0.80022, 0.80747, 0.81457, 0.82151, 0.82831, + 0.83496, 0.84145, 0.84779, 0.85398, 0.86001, 0.86588, 0.87160, 0.87716, + 0.88257, 0.88782, 0.89291, 0.89785, 0.90264, 0.90728, 0.91176, 0.91610, + 0.92028, 0.92432, 0.92822, 0.93197, 0.93558, 0.93906, 0.94240, 0.94560, + 0.94867, 0.95162, 0.95444, 0.95713, 0.95971, 0.96217, 0.96451, 0.96674, + 0.96887, 0.97089, 0.97281, 0.97463, 0.97635, 0.97799, 0.97953, 0.98099, + 0.98236, 0.98366, 0.98488, 0.98602, 0.98710, 0.98811, 0.98905, 0.98994, + 0.99076, 0.99153, 0.99225, 0.99291, 0.99353, 0.99411, 0.99464, 0.99513, + 0.99558, 0.99600, 0.99639, 0.99674, 0.99706, 0.99736, 0.99763, 0.99788, + 0.99811, 0.99831, 0.99850, 0.99867, 0.99882, 0.99895, 0.99908, 0.99919, + 0.99929, 0.99938, 0.99946, 0.99953, 0.99959, 0.99965, 0.99969, 0.99974, + 0.99978, 0.99981, 0.99984, 0.99986, 0.99988, 0.99990, 0.99992, 0.99993, + 0.99994, 0.99995, 0.99996, 0.99997, 0.99998, 0.99998, 0.99998, 0.99999, + 0.99999, 0.99999, 0.99999, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, + 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000 +}; + +mpeg3_complex_t cmplx_mult(mpeg3_complex_t a, mpeg3_complex_t b) +{ + mpeg3_complex_t ret; + + ret.real = a.real * b.real - a.imag * b.imag; + ret.imag = a.real * b.imag + a.imag * b.real; + + return ret; +} + +int mpeg3audio_imdct_init(mpeg3audio_t *audio) +{ + int i, k; + mpeg3_complex_t angle_step; + mpeg3_complex_t current_angle; + +/* Twiddle factors to turn IFFT into IMDCT */ + for(i = 0; i < AC3_N / 4; i++) + { + mpeg3_xcos1[i] = -cos(2.0f * M_PI * (8 * i + 1 ) / ( 8 * AC3_N)); + mpeg3_xsin1[i] = -sin(2.0f * M_PI * (8 * i + 1 ) / ( 8 * AC3_N)); + } + +/* More twiddle factors to turn IFFT into IMDCT */ + for(i = 0; i < AC3_N / 8; i++) + { + mpeg3_xcos2[i] = -cos(2.0f * M_PI * (8 * i + 1 ) / ( 4 * AC3_N)); + mpeg3_xsin2[i] = -sin(2.0f * M_PI * (8 * i + 1 ) / ( 4 * AC3_N)); + } + +/* Canonical twiddle factors for FFT */ +#if defined(USE_FIXED_POINT) && !defined(PRINT_FIXED_POINT_TABLES) + for(i = 0; i < 7; i++) + { + audio->ac3_w[i] = (mpeg3_complex_t*)ac3_w_fixedpoints[i]; + } +#else + audio->ac3_w[0] = audio->ac3_w_1; + audio->ac3_w[1] = audio->ac3_w_2; + audio->ac3_w[2] = audio->ac3_w_4; + audio->ac3_w[3] = audio->ac3_w_8; + audio->ac3_w[4] = audio->ac3_w_16; + audio->ac3_w[5] = audio->ac3_w_32; + audio->ac3_w[6] = audio->ac3_w_64; + + for(i = 0; i < 7; i++) + { + angle_step.real = cos(-2.0f * M_PI / (1 << (i + 1))); + angle_step.imag = sin(-2.0f * M_PI / (1 << (i + 1))); + + current_angle.real = 1.0f; + current_angle.imag = 0.0f; + + for (k = 0; k < 1 << i; k++) + { + audio->ac3_w[i][k] = current_angle; + current_angle = cmplx_mult(current_angle, angle_step); + } + } + +#ifdef PRINT_FIXED_POINT_TABLES + printf("#ifdef USE_FP_TABLES\n"); + printf("static long mpeg3_xcos1_fixedpoints[] = {"); + for(i = 0; i < AC3_N / 4; i++) { + printf("%c0x%08x,", i%8?' ':'\n', mpeg3_xcos1[i].fixedPoint()); + } + printf("\n};\nstatic mpeg3_real_t *mpeg3_xcos1 = \n" + "(mpeg3_real_t*)mpeg3_xcos1_fixedpoints;\n"); + + printf("static long mpeg3_xsin1_fixedpoints[] = {"); + for(i = 0; i < AC3_N / 4; i++) { + printf("%c0x%08x,", i%8?' ':'\n', mpeg3_xsin1[i].fixedPoint()); + } + printf("\n};\nstatic mpeg3_real_t *mpeg3_xsin1 = \n" + "(mpeg3_real_t*)mpeg3_xsin1_fixedpoints;\n"); + + + printf("static long mpeg3_xcos2_fixedpoints[] = {"); + for(i = 0; i < AC3_N / 4; i++) { + printf("%c0x%08x,", i%8?' ':'\n', mpeg3_xcos2[i].fixedPoint()); + } + printf("\n};\nstatic mpeg3_real_t *mpeg3_xcos2 = \n" + "(mpeg3_real_t*)mpeg3_xcos2_fixedpoints;\n"); + + printf("static long mpeg3_xsin2_fixedpoints[] = {"); + for(i = 0; i < AC3_N / 4; i++) { + printf("%c0x%08x,", i%8?' ':'\n', mpeg3_xsin2[i].fixedPoint()); + } + printf("\n};\nstatic mpeg3_real_t *mpeg3_xsin2 = \n" + "(mpeg3_real_t*)mpeg3_xsin2_fixedpoints;\n"); + + + printf("typedef struct { long r, i; } fixed_cmplx;\n"); + for(i = 0; i < 7; i++) + { + printf("fixed_cmplx ac3_w_d%d[] = { ", 1<ac3_w[i][k].real.fixedPoint(), + audio->ac3_w[i][k].imag.fixedPoint()); + } + printf("};\n"); + } + + printf("fixed_cmplx *ac3_w_fixedpoints[] = {\n"); + for(i = 0; i < 7; i++) + { + printf("ac3_w_d%d, ", 1<ac3_imdct_buf; + +/* Pre IFFT complex multiply plus IFFT cmplx conjugate */ + for(i = 0; i < AC3_N / 4; i++) + { + buf[i].real = (data[AC3_N / 2 - 2 * i - 1] * mpeg3_xcos1[i]) - (data[2 * i] * mpeg3_xsin1[i]); + buf[i].imag = -((data[2 * i] * mpeg3_xcos1[i]) + (data[AC3_N / 2 - 2 * i - 1] * mpeg3_xsin1[i])); + } + +/* Bit reversed shuffling */ + for(i = 0; i < AC3_N / 4; i++) + { + k = mpeg3_bit_reverse_512[i]; + if(k < i) + swap_cmplx(&buf[i], &buf[k]); + } + +/* FFT Merge */ + for(m = 0; m < 7; m++) + { + if(m) + two_m = (1 << m); + else + two_m = 1; + + two_m_plus_one = (1 << (m + 1)); + + for(k = 0; k < two_m; k++) + { + for(i = 0; i < AC3_N / 4; i += two_m_plus_one) + { + p = k + i; + q = p + two_m; + tmp_a_r = buf[p].real; + tmp_a_i = buf[p].imag; + tmp_b_r = buf[q].real * audio->ac3_w[m][k].real - buf[q].imag * audio->ac3_w[m][k].imag; + tmp_b_i = buf[q].imag * audio->ac3_w[m][k].real + buf[q].real * audio->ac3_w[m][k].imag; + buf[p].real = tmp_a_r + tmp_b_r; + buf[p].imag = tmp_a_i + tmp_b_i; + buf[q].real = tmp_a_r - tmp_b_r; + buf[q].imag = tmp_a_i - tmp_b_i; + } + } + } + +/* Post IFFT complex multiply plus IFFT complex conjugate*/ + for(i = 0; i < AC3_N / 4; i++) + { + tmp_a_r = buf[i].real; + tmp_a_i = -buf[i].imag; + buf[i].real = (tmp_a_r * mpeg3_xcos1[i]) - (tmp_a_i * mpeg3_xsin1[i]); + buf[i].imag = (tmp_a_r * mpeg3_xsin1[i]) + (tmp_a_i * mpeg3_xcos1[i]); + } + + y_ptr = y; + delay_ptr = delay; + window_ptr = mpeg3_window; + +/* Window and convert to real valued signal */ + for(i = 0; i < AC3_N / 8; i++) + { + *y_ptr = -buf[AC3_N / 8 + i].imag * *window_ptr++ + *delay_ptr++; + y_ptr += step; + *y_ptr = buf[AC3_N / 8 - i - 1].real * *window_ptr++ + *delay_ptr++; + y_ptr += step; + } + + for(i = 0; i < AC3_N / 8; i++) + { + *y_ptr = -buf[i].real * *window_ptr++ + *delay_ptr++; + y_ptr += step; + *y_ptr = buf[AC3_N / 4 - i - 1].imag * *window_ptr++ + *delay_ptr++; + y_ptr += step; + } + +/* The trailing edge of the window goes into the delay line */ + delay_ptr = delay; + + for(i = 0; i < AC3_N / 8; i++) + { + *delay_ptr++ = -buf[AC3_N / 8 + i].real * *--window_ptr; + *delay_ptr++ = buf[AC3_N / 8 - i - 1].imag * *--window_ptr; + } + + for(i = 0; i < AC3_N / 8; i++) + { + *delay_ptr++ = buf[i].imag * *--window_ptr; + *delay_ptr++ = -buf[AC3_N / 4 - i - 1].real * *--window_ptr; + } +} + +void mpeg3audio_ac3_imdct_do_256(mpeg3audio_t *audio, + mpeg3_real_t data[], + mpeg3_real_t *y, + int step, + mpeg3_real_t *delay) +{ + int i, k; + int p, q; + int m; + int two_m; + int two_m_plus_one; + mpeg3_complex_t *buf = audio->ac3_imdct_buf; + mpeg3_real_t *y_ptr; + mpeg3_real_t *delay_ptr; + mpeg3_real_t *window_ptr; + + mpeg3_real_t tmp_a_i; + mpeg3_real_t tmp_a_r; + mpeg3_real_t tmp_b_i; + mpeg3_real_t tmp_b_r; + + mpeg3_complex_t *buf_1, *buf_2; + + buf_1 = &buf[0]; + buf_2 = &buf[64]; + +/* Pre IFFT complex multiply plus IFFT cmplx conjugate */ + for(k = 0; k < AC3_N / 8; k++) + { + p = 2 * (AC3_N / 4 - 2 * k - 1); + q = 2 * (2 * k); + + buf_1[k].real = data[p] * mpeg3_xcos2[k] - data[q] * mpeg3_xsin2[k]; + buf_1[k].imag = - (data[q] * mpeg3_xcos2[k] + data[p] * mpeg3_xsin2[k]); + buf_2[k].real = data[p + 1] * mpeg3_xcos2[k] - data[q + 1] * mpeg3_xsin2[k]; + buf_2[k].imag = - (data[q + 1] * mpeg3_xcos2[k] + data[p + 1] * mpeg3_xsin2[k]); + } + +/* IFFT Bit reversed shuffling */ + for(i = 0; i < AC3_N / 8; i++) + { + k = mpeg3_bit_reverse_256[i]; + if(k < i) + { + swap_cmplx(&buf_1[i], &buf_1[k]); + swap_cmplx(&buf_2[i], &buf_2[k]); + } + } + +/* FFT Merge */ + for(m = 0; m < 6; m++) + { + if(m) + two_m = (1 << m); + else + two_m = 1; + + two_m_plus_one = (1 << (m + 1)); + + for(k = 0; k < two_m; k++) + { + for(i = 0; i < AC3_N / 8; i += two_m_plus_one) + { + p = k + i; + q = p + two_m; +/* Do block 1 */ + tmp_a_r = buf_1[p].real; + tmp_a_i = buf_1[p].imag; + tmp_b_r = buf_1[q].real * audio->ac3_w[m][k].real - buf_1[q].imag * audio->ac3_w[m][k].imag; + tmp_b_i = buf_1[q].imag * audio->ac3_w[m][k].real + buf_1[q].real * audio->ac3_w[m][k].imag; + buf_1[p].real = tmp_a_r + tmp_b_r; + buf_1[p].imag = tmp_a_i + tmp_b_i; + buf_1[q].real = tmp_a_r - tmp_b_r; + buf_1[q].imag = tmp_a_i - tmp_b_i; + +/* Do block 2 */ + tmp_a_r = buf_2[p].real; + tmp_a_i = buf_2[p].imag; + tmp_b_r = buf_2[q].real * audio->ac3_w[m][k].real - buf_2[q].imag * audio->ac3_w[m][k].imag; + tmp_b_i = buf_2[q].imag * audio->ac3_w[m][k].real + buf_2[q].real * audio->ac3_w[m][k].imag; + buf_2[p].real = tmp_a_r + tmp_b_r; + buf_2[p].imag = tmp_a_i + tmp_b_i; + buf_2[q].real = tmp_a_r - tmp_b_r; + buf_2[q].imag = tmp_a_i - tmp_b_i; + } + } + } + +/* Post IFFT complex multiply */ + for(i = 0; i < AC3_N / 8; i++) + { + tmp_a_r = buf_1[i].real; + tmp_a_i = -buf_1[i].imag; + buf_1[i].real = (tmp_a_r * mpeg3_xcos2[i]) - (tmp_a_i * mpeg3_xsin2[i]); + buf_1[i].imag = (tmp_a_r * mpeg3_xsin2[i]) + (tmp_a_i * mpeg3_xcos2[i]); + tmp_a_r = buf_2[i].real; + tmp_a_i = -buf_2[i].imag; + buf_2[i].real = (tmp_a_r * mpeg3_xcos2[i]) - (tmp_a_i * mpeg3_xsin2[i]); + buf_2[i].imag = (tmp_a_r * mpeg3_xsin2[i]) + (tmp_a_i * mpeg3_xcos2[i]); + } + +/* Window and convert to real valued signal */ + y_ptr = y; + delay_ptr = delay; + window_ptr = mpeg3_window; + + for(i = 0; i < AC3_N / 8; i++) + { + *y_ptr = -buf[AC3_N / 8 + i].imag * *window_ptr++ + *delay_ptr++; + y_ptr += step; + *y_ptr = buf[AC3_N / 8 - i - 1].real * *window_ptr++ + *delay_ptr++; + y_ptr += step; + } + + for(i = 0; i < AC3_N / 8; i++) + { + *y_ptr = -buf[i].real * *window_ptr++ + *delay_ptr++; + y_ptr += step; + *y_ptr = buf[AC3_N / 4 - i - 1].imag * *window_ptr++ + *delay_ptr++; + y_ptr += step; + } + +/* The trailing edge of the window goes into the delay line */ + delay_ptr = delay; + + for(i = 0; i < AC3_N / 8; i++) + { + *delay_ptr++ = -buf[AC3_N / 8 + i].real * *--window_ptr; + *delay_ptr++ = buf[AC3_N / 8 - i - 1].imag * *--window_ptr; + } + + for(i = 0; i < AC3_N / 8; i++) + { + *delay_ptr++ = buf[i].imag * *--window_ptr; + *delay_ptr++ = -buf[AC3_N / 4 - i - 1].real * *--window_ptr; + } +} + +int mpeg3audio_ac3_imdct(mpeg3audio_t *audio, + mpeg3_ac3bsi_t *bsi, + mpeg3_ac3audblk_t *audblk, + mpeg3ac3_stream_samples_t samples) +{ + int i; + + for(i = 0; i < bsi->nfchans; i++) + { + if(audblk->blksw[i]) + mpeg3audio_ac3_imdct_do_256(audio, + samples[i], + audio->pcm_sample + audio->pcm_point + i, + bsi->nfchans, + audio->ac3_delay[i]); + else + mpeg3audio_ac3_imdct_do_512(audio, + samples[i], + audio->pcm_sample + audio->pcm_point + i, + bsi->nfchans, + audio->ac3_delay[i]); + } + audio->pcm_point += AC3_N / 2 * bsi->nfchans; + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/exponents.c b/core/multimedia/opieplayer/libmpeg3/audio/exponents.c new file mode 100644 index 0000000..deda9b9 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/exponents.c @@ -0,0 +1,141 @@ +/* + * + * exponents.c Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of libmpeg3 + * + * libmpeg3 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. + * + * libmpeg3 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. + * + */ + +#include "mpeg3audio.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include + +/* Exponent defines */ +#define UNPACK_FBW 1 +#define UNPACK_CPL 2 +#define UNPACK_LFE 4 + +static inline int mpeg3audio_ac3_exp_unpack_ch(unsigned int type, + unsigned int expstr, + unsigned int ngrps, + unsigned int initial_exp, + unsigned short exps[], + unsigned short *dest) +{ + int i, j; + int exp_acc; + int exp_1, exp_2, exp_3; + + if(expstr == MPEG3_EXP_REUSE) + return 0; + +/* Handle the initial absolute exponent */ + exp_acc = initial_exp; + j = 0; + +/* In the case of a fbw channel then the initial absolute value is + * also an exponent */ + if(type != UNPACK_CPL) + dest[j++] = exp_acc; + +/* Loop through the groups and fill the dest array appropriately */ + for(i = 0; i < ngrps; i++) + { + if(exps[i] > 124) + { + fprintf(stderr, "mpeg3audio_ac3_exp_unpack_ch: Invalid exponent %d\n", exps[i]); + return 1; + } + + exp_1 = exps[i] / 25; + exp_2 = (exps[i] % 25) / 5; + exp_3 = (exps[i] % 25) % 5; + + exp_acc += (exp_1 - 2); + + switch(expstr) + { + case MPEG3_EXP_D45: + dest[j++] = exp_acc; + dest[j++] = exp_acc; + case MPEG3_EXP_D25: + dest[j++] = exp_acc; + case MPEG3_EXP_D15: + dest[j++] = exp_acc; + } + + exp_acc += (exp_2 - 2); + + switch(expstr) + { + case MPEG3_EXP_D45: + dest[j++] = exp_acc; + dest[j++] = exp_acc; + case MPEG3_EXP_D25: + dest[j++] = exp_acc; + case MPEG3_EXP_D15: + dest[j++] = exp_acc; + } + + exp_acc += (exp_3 - 2); + + switch(expstr) + { + case MPEG3_EXP_D45: + dest[j++] = exp_acc; + dest[j++] = exp_acc; + case MPEG3_EXP_D25: + dest[j++] = exp_acc; + case MPEG3_EXP_D15: + dest[j++] = exp_acc; + } + } + return 0; +} + +int mpeg3audio_ac3_exponent_unpack(mpeg3audio_t *audio, + mpeg3_ac3bsi_t *bsi, + mpeg3_ac3audblk_t *audblk) +{ + int i, result = 0; + + for(i = 0; i < bsi->nfchans; i++) + result |= mpeg3audio_ac3_exp_unpack_ch(UNPACK_FBW, + audblk->chexpstr[i], + audblk->nchgrps[i], + audblk->exps[i][0], + &audblk->exps[i][1], + audblk->fbw_exp[i]); + + if(audblk->cplinu && !result) + result |= mpeg3audio_ac3_exp_unpack_ch(UNPACK_CPL, + audblk->cplexpstr, + audblk->ncplgrps, + audblk->cplabsexp << 1, + audblk->cplexps, + &audblk->cpl_exp[audblk->cplstrtmant]); + + if(bsi->lfeon && !result) + result |= mpeg3audio_ac3_exp_unpack_ch(UNPACK_LFE, + audblk->lfeexpstr, + 2, + audblk->lfeexps[0], + &audblk->lfeexps[1], + audblk->lfe_exp); + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/fptables.h b/core/multimedia/opieplayer/libmpeg3/audio/fptables.h new file mode 100644 index 0000000..2836984 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/fptables.h @@ -0,0 +1,1556 @@ +#ifdef USE_FP_TABLES +static long mpeg3_xcos1_fixedpoints[] = { +0xffff8001, 0xffff8004, 0xffff800c, 0xffff8019, 0xffff802a, 0xffff8041, 0xffff805d, 0xffff807e, +0xffff80a3, 0xffff80ce, 0xffff80fd, 0xffff8131, 0xffff816b, 0xffff81a9, 0xffff81ec, 0xffff8233, +0xffff8280, 0xffff82d1, 0xffff8328, 0xffff8383, 0xffff83e3, 0xffff8447, 0xffff84b1, 0xffff851f, +0xffff8592, 0xffff860a, 0xffff8686, 0xffff8707, 0xffff878d, 0xffff8817, 0xffff88a6, 0xffff893a, +0xffff89d2, 0xffff8a6f, 0xffff8b10, 0xffff8bb6, 0xffff8c60, 0xffff8d0f, 0xffff8dc2, 0xffff8e7a, +0xffff8f35, 0xffff8ff6, 0xffff90ba, 0xffff9183, 0xffff9250, 0xffff9322, 0xffff93f7, 0xffff94d1, +0xffff95af, 0xffff9691, 0xffff9777, 0xffff9861, 0xffff994f, 0xffff9a41, 0xffff9b37, 0xffff9c31, +0xffff9d2e, 0xffff9e30, 0xffff9f35, 0xffffa03e, 0xffffa14b, 0xffffa25b, 0xffffa36f, 0xffffa487, +0xffffa5a2, 0xffffa6c0, 0xffffa7e2, 0xffffa907, 0xffffaa30, 0xffffab5c, 0xffffac8b, 0xffffadbe, +0xffffaef4, 0xffffb02c, 0xffffb168, 0xffffb2a7, 0xffffb3e9, 0xffffb52e, 0xffffb676, 0xffffb7c0, +0xffffb90d, 0xffffba5d, 0xffffbbb0, 0xffffbd06, 0xffffbe5e, 0xffffbfb8, 0xffffc115, 0xffffc274, +0xffffc3d6, 0xffffc53a, 0xffffc6a1, 0xffffc809, 0xffffc974, 0xffffcae1, 0xffffcc50, 0xffffcdc0, +0xffffcf33, 0xffffd0a8, 0xffffd21e, 0xffffd397, 0xffffd511, 0xffffd68c, 0xffffd80a, 0xffffd988, +0xffffdb09, 0xffffdc8a, 0xffffde0d, 0xffffdf92, 0xffffe117, 0xffffe29e, 0xffffe426, 0xffffe5af, +0xffffe739, 0xffffe8c4, 0xffffea50, 0xffffebdd, 0xffffed6a, 0xffffeef8, 0xfffff087, 0xfffff217, +0xfffff3a7, 0xfffff537, 0xfffff6c8, 0xfffff859, 0xfffff9eb, 0xfffffb7d, 0xfffffd0f, 0xfffffea1, +}; +static mpeg3_real_t *mpeg3_xcos1 = +(mpeg3_real_t*)mpeg3_xcos1_fixedpoints; +static long mpeg3_xsin1_fixedpoints[] = { +0xffffffce, 0xfffffe3c, 0xfffffcaa, 0xfffffb18, 0xfffff986, 0xfffff7f5, 0xfffff664, 0xfffff4d3, +0xfffff343, 0xfffff1b3, 0xfffff023, 0xffffee95, 0xffffed07, 0xffffeb79, 0xffffe9ed, 0xffffe861, +0xffffe6d6, 0xffffe54d, 0xffffe3c4, 0xffffe23c, 0xffffe0b6, 0xffffdf30, 0xffffddac, 0xffffdc2a, +0xffffdaa8, 0xffffd928, 0xffffd7aa, 0xffffd62d, 0xffffd4b2, 0xffffd338, 0xffffd1c1, 0xffffd04b, +0xffffced6, 0xffffcd64, 0xffffcbf4, 0xffffca85, 0xffffc919, 0xffffc7af, 0xffffc647, 0xffffc4e1, +0xffffc37d, 0xffffc21c, 0xffffc0bd, 0xffffbf61, 0xffffbe07, 0xffffbcb0, 0xffffbb5b, 0xffffba09, +0xffffb8ba, 0xffffb76d, 0xffffb623, 0xffffb4dc, 0xffffb398, 0xffffb257, 0xffffb119, 0xffffafde, +0xffffaea6, 0xffffad71, 0xffffac3f, 0xffffab11, 0xffffa9e6, 0xffffa8be, 0xffffa799, 0xffffa678, +0xffffa55b, 0xffffa440, 0xffffa32a, 0xffffa217, 0xffffa107, 0xffff9ffc, 0xffff9ef3, 0xffff9def, +0xffff9cef, 0xffff9bf2, 0xffff9af9, 0xffff9a04, 0xffff9913, 0xffff9826, 0xffff973d, 0xffff9658, +0xffff9577, 0xffff949a, 0xffff93c1, 0xffff92ed, 0xffff921d, 0xffff9151, 0xffff9089, 0xffff8fc5, +0xffff8f06, 0xffff8e4b, 0xffff8d95, 0xffff8ce3, 0xffff8c35, 0xffff8b8c, 0xffff8ae7, 0xffff8a47, +0xffff89ac, 0xffff8915, 0xffff8882, 0xffff87f4, 0xffff876b, 0xffff86e7, 0xffff8667, 0xffff85eb, +0xffff8575, 0xffff8503, 0xffff8496, 0xffff842e, 0xffff83ca, 0xffff836c, 0xffff8312, 0xffff82bd, +0xffff826c, 0xffff8221, 0xffff81da, 0xffff8199, 0xffff815c, 0xffff8124, 0xffff80f1, 0xffff80c3, +0xffff8099, 0xffff8075, 0xffff8056, 0xffff803b, 0xffff8026, 0xffff8015, 0xffff8009, 0xffff8002, +}; +static mpeg3_real_t *mpeg3_xsin1 = +(mpeg3_real_t*)mpeg3_xsin1_fixedpoints; +static long mpeg3_xcos2_fixedpoints[] = { +0xffff8001, 0xffff800d, 0xffff802d, 0xffff8061, 0xffff80a8, 0xffff8103, 0xffff8172, 0xffff81f4, +0xffff828a, 0xffff8333, 0xffff83ef, 0xffff84be, 0xffff85a1, 0xffff8696, 0xffff879e, 0xffff88b9, +0xffff89e5, 0xffff8b25, 0xffff8c76, 0xffff8dd9, 0xffff8f4d, 0xffff90d3, 0xffff926a, 0xffff9412, +0xffff95cb, 0xffff9794, 0xffff996d, 0xffff9b56, 0xffff9d4e, 0xffff9f56, 0xffffa16d, 0xffffa392, +0xffffa5c5, 0xffffa807, 0xffffaa55, 0xffffacb2, 0xffffaf1b, 0xffffb190, 0xffffb411, 0xffffb69f, +0xffffb937, 0xffffbbdb, 0xffffbe89, 0xffffc141, 0xffffc403, 0xffffc6ce, 0xffffc9a1, 0xffffcc7e, +0xffffcf62, 0xffffd24d, 0xffffd540, 0xffffd839, 0xffffdb39, 0xffffde3e, 0xffffe148, 0xffffe457, +0xffffe76a, 0xffffea81, 0xffffed9c, 0xfffff0b9, 0xfffff3d9, 0xfffff6fa, 0xfffffa1d, 0xfffffd41, +0xffffff9c, 0xfffffc78, 0xfffff954, 0xfffff632, 0xfffff311, 0xffffeff2, 0xffffecd5, 0xffffe9bb, +0xffffe6a5, 0xffffe393, 0xffffe085, 0xffffdd7c, 0xffffda78, 0xffffd77a, 0xffffd483, 0xffffd192, +0xffffcea8, 0xffffcbc6, 0xffffc8ec, 0xffffc61a, 0xffffc351, 0xffffc092, 0xffffbddc, 0xffffbb31, +0xffffb890, 0xffffb5fa, 0xffffb370, 0xffffb0f1, 0xffffae7f, 0xffffac19, 0xffffa9c0, 0xffffa775, +0xffffa537, 0xffffa307, 0xffffa0e6, 0xffff9ed3, 0xffff9ccf, 0xffff9ada, 0xffff98f5, 0xffff9720, +0xffff955b, 0xffff93a7, 0xffff9203, 0xffff9070, 0xffff8eee, 0xffff8d7e, 0xffff8c20, 0xffff8ad3, +0xffff8998, 0xffff8870, 0xffff875a, 0xffff8657, 0xffff8566, 0xffff8489, 0xffff83be, 0xffff8307, +0xffff8263, 0xffff81d2, 0xffff8155, 0xffff80eb, 0xffff8095, 0xffff8052, 0xffff8023, 0xffff8008, +}; +static mpeg3_real_t *mpeg3_xcos2 = +(mpeg3_real_t*)mpeg3_xcos2_fixedpoints; +static long mpeg3_xsin2_fixedpoints[] = { +0xffffff9c, 0xfffffc78, 0xfffff954, 0xfffff632, 0xfffff311, 0xffffeff2, 0xffffecd5, 0xffffe9bb, +0xffffe6a5, 0xffffe393, 0xffffe085, 0xffffdd7c, 0xffffda78, 0xffffd77a, 0xffffd483, 0xffffd192, +0xffffcea8, 0xffffcbc6, 0xffffc8ec, 0xffffc61a, 0xffffc351, 0xffffc092, 0xffffbddc, 0xffffbb31, +0xffffb890, 0xffffb5fa, 0xffffb370, 0xffffb0f1, 0xffffae7f, 0xffffac19, 0xffffa9c0, 0xffffa775, +0xffffa537, 0xffffa307, 0xffffa0e6, 0xffff9ed3, 0xffff9ccf, 0xffff9ada, 0xffff98f5, 0xffff9720, +0xffff955b, 0xffff93a7, 0xffff9203, 0xffff9070, 0xffff8eee, 0xffff8d7e, 0xffff8c20, 0xffff8ad3, +0xffff8998, 0xffff8870, 0xffff875a, 0xffff8657, 0xffff8566, 0xffff8489, 0xffff83be, 0xffff8307, +0xffff8263, 0xffff81d2, 0xffff8155, 0xffff80eb, 0xffff8095, 0xffff8052, 0xffff8023, 0xffff8008, +0x00000004, 0x00000007, 0x0000000c, 0x00000010, 0x00000015, 0x0000001c, 0x00000023, 0x0000002a, +0x00000033, 0x0000003d, 0x00000048, 0x00000053, 0x00000061, 0x0000006f, 0x0000007f, 0x00000091, +0x000000a4, 0x000000b8, 0x000000cf, 0x000000e7, 0x00000101, 0x0000011d, 0x0000013b, 0x0000015b, +0x0000017e, 0x000001a3, 0x000001ca, 0x000001f4, 0x00000220, 0x0000024f, 0x00000281, 0x000002b7, +0x000002ef, 0x0000032a, 0x00000368, 0x000003aa, 0x000003ee, 0x00000437, 0x00000483, 0x000004d3, +0x00000526, 0x0000057e, 0x000005d9, 0x00000639, 0x0000069c, 0x00000704, 0x0000076f, 0x000007e0, +0x00000854, 0x000008cd, 0x0000094b, 0x000009cd, 0x00000a54, 0x00000adf, 0x00000b6f, 0x00000c04, +0x00000c9e, 0x00000d3d, 0x00000de0, 0x00000e89, 0x00000f36, 0x00000fe8, 0x0000109f, 0x0000115c, +}; +static mpeg3_real_t *mpeg3_xsin2 = +(mpeg3_real_t*)mpeg3_xsin2_fixedpoints; +typedef struct { long r, i; } fixed_cmplx; +fixed_cmplx ac3_w_d1[] = { + { 0x00008000, 0x00000000 },}; +fixed_cmplx ac3_w_d2[] = { + { 0x00008000, 0x00000000 }, { 0x00000000, 0xffff8000 },}; +fixed_cmplx ac3_w_d4[] = { + { 0x00008000, 0x00000000 }, { 0x00005a82, 0xffffa57e }, { 0x00000000, 0xffff8002 }, { 0xffffa580, 0xffffa580 },}; +fixed_cmplx ac3_w_d8[] = { + { 0x00008000, 0x00000000 }, { 0x00007641, 0xffffcf05 }, { 0x00005a81, 0xffffa580 }, { 0x000030fb, 0xffff89c4 }, + { 0x00000002, 0xffff8007 }, { 0xffffcf09, 0xffff89c6 }, { 0xffffa587, 0xffffa583 }, { 0xffff89cb, 0xffffcf05 },}; +fixed_cmplx ac3_w_d16[] = { + { 0x00008000, 0x00000000 }, { 0x00007d8a, 0xffffe708 }, { 0x00007642, 0xffffcf06 }, { 0x00006a6e, 0xffffb8e7 }, + { 0x00005a84, 0xffffa583 }, { 0x00004720, 0xffff9599 }, { 0x00003100, 0xffff89c6 }, { 0x000018ff, 0xffff827e }, + { 0x00000008, 0xffff8008 }, { 0xffffe711, 0xffff827d }, { 0xffffcf11, 0xffff89c4 }, { 0xffffb8f2, 0xffff9595 }, + { 0xffffa58e, 0xffffa57d }, { 0xffff95a5, 0xffffb8df }, { 0xffff89d2, 0xffffcefd }, { 0xffff8289, 0xffffe6fc },}; +fixed_cmplx ac3_w_d32[] = { + { 0x00008000, 0x00000000 }, { 0x00007f62, 0xfffff375 }, { 0x00007d8a, 0xffffe70a }, { 0x00007a7d, 0xffffdadc }, + { 0x00007642, 0xffffcf0a }, { 0x000070e4, 0xffffc3b1 }, { 0x00006a70, 0xffffb8ed }, { 0x000062f6, 0xffffaed7 }, + { 0x00005a88, 0xffffa58a }, { 0x0000513b, 0xffff9d1b }, { 0x00004726, 0xffff95a1 }, { 0x00003c62, 0xffff8f2d }, + { 0x00003109, 0xffff89cf }, { 0x00002538, 0xffff8593 }, { 0x0000190b, 0xffff8286 }, { 0x00000ca1, 0xffff80ad }, + { 0x00000017, 0xffff800f }, { 0xfffff38d, 0xffff80ab }, { 0xffffe723, 0xffff8281 }, { 0xffffdaf6, 0xffff858b }, + { 0xffffcf25, 0xffff89c4 }, { 0xffffc3cc, 0xffff8f1f }, { 0xffffb908, 0xffff9591 }, { 0xffffaef3, 0xffff9d09 }, + { 0xffffa5a6, 0xffffa575 }, { 0xffff9d37, 0xffffaebf }, { 0xffff95bb, 0xffffb8d2 }, { 0xffff8f46, 0xffffc393 }, + { 0xffff89e7, 0xffffcee9 }, { 0xffff85aa, 0xffffdab8 }, { 0xffff829b, 0xffffe6e3 }, { 0xffff80c1, 0xfffff34b },}; +fixed_cmplx ac3_w_d64[] = { + { 0x00008000, 0x00000000 }, { 0x00007fd8, 0xfffff9b9 }, { 0x00007f62, 0xfffff376 }, { 0x00007e9d, 0xffffed3b }, + { 0x00007d8a, 0xffffe70c }, { 0x00007c29, 0xffffe0ec }, { 0x00007a7c, 0xffffdae0 }, { 0x00007883, 0xffffd4eb }, + { 0x00007641, 0xffffcf11 }, { 0x000073b6, 0xffffc955 }, { 0x000070e3, 0xffffc3bb }, { 0x00006dcb, 0xffffbe45 }, + { 0x00006a6f, 0xffffb8f8 }, { 0x000066d2, 0xffffb3d7 }, { 0x000062f5, 0xffffaee5 }, { 0x00005edc, 0xffffaa25 }, + { 0x00005a89, 0xffffa59a }, { 0x000055fe, 0xffffa147 }, { 0x0000513e, 0xffff9d2e }, { 0x00004c4c, 0xffff9952 }, + { 0x0000472b, 0xffff95b6 }, { 0x000041de, 0xffff925b }, { 0x00003c69, 0xffff8f44 }, { 0x000036cf, 0xffff8c72 }, + { 0x00003113, 0xffff89e7 }, { 0x00002b39, 0xffff87a4 }, { 0x00002544, 0xffff85ac }, { 0x00001f39, 0xffff8400 }, + { 0x0000191b, 0xffff82a0 }, { 0x000012ed, 0xffff818d }, { 0x00000cb4, 0xffff80c8 }, { 0x00000673, 0xffff8051 }, + { 0x0000002d, 0xffff8029 }, { 0xfffff9e8, 0xffff804f }, { 0xfffff3a7, 0xffff80c3 }, { 0xffffed6e, 0xffff8186 }, + { 0xffffe741, 0xffff8297 }, { 0xffffe123, 0xffff83f5 }, { 0xffffdb18, 0xffff859f }, { 0xffffd524, 0xffff8795 }, + { 0xffffcf4b, 0xffff89d5 }, { 0xffffc990, 0xffff8c5d }, { 0xffffc3f7, 0xffff8f2d }, { 0xffffbe82, 0xffff9242 }, + { 0xffffb936, 0xffff959b }, { 0xffffb416, 0xffff9935 }, { 0xffffaf24, 0xffff9d0f }, { 0xffffaa64, 0xffffa125 }, + { 0xffffa5d9, 0xffffa575 }, { 0xffffa186, 0xffffa9fd }, { 0xffff9d6d, 0xffffaeba }, { 0xffff9990, 0xffffb3a9 }, + { 0xffff95f3, 0xffffb8c7 }, { 0xffff9297, 0xffffbe11 }, { 0xffff8f7f, 0xffffc383 }, { 0xffff8cac, 0xffffc91a }, + { 0xffff8a20, 0xffffced3 }, { 0xffff87dc, 0xffffd4aa }, { 0xffff85e2, 0xffffda9c }, { 0xffff8434, 0xffffe0a5 }, + { 0xffff82d2, 0xffffe6c1 }, { 0xffff81be, 0xffffecec }, { 0xffff80f7, 0xfffff323 }, { 0xffff807e, 0xfffff962 },}; +fixed_cmplx *ac3_w_fixedpoints[] = { +ac3_w_d1, ac3_w_d2, ac3_w_d4, ac3_w_d8, ac3_w_d16, ac3_w_d32, ac3_w_d64, }; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_muls_data[] = { +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xffff5556, 0xffff788b, 0xffff947d, 0xffffaaab, 0xffffbc46, 0xffffca3f, 0xffffd556, 0xffffde23, +0xffffe520, 0xffffeaab, 0xffffef12, 0xfffff290, 0xfffff556, 0xfffff789, 0xfffff948, 0xfffffaab, +0xfffffbc5, 0xfffffca4, 0xfffffd56, 0xfffffde3, 0xfffffe52, 0xfffffeab, 0xfffffef2, 0xffffff29, +0xffffff56, 0xffffff79, 0xffffff95, 0xffffffab, 0xffffffbd, 0xffffffcb, 0xffffffd6, 0xffffffdf, +0xffffffe6, 0xffffffeb, 0xfffffff0, 0xfffffff3, 0xfffffff6, 0xfffffff8, 0xfffffffa, 0xfffffffb, +0xfffffffc, 0xfffffffd, 0xfffffffe, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x0000aaaa, 0x00008775, 0x00006b83, 0x00005555, 0x000043ba, 0x000035c1, 0x00002aaa, 0x000021dd, +0x00001ae0, 0x00001555, 0x000010ee, 0x00000d70, 0x00000aaa, 0x00000877, 0x000006b8, 0x00000555, +0x0000043b, 0x0000035c, 0x000002aa, 0x0000021d, 0x000001ae, 0x00000155, 0x0000010e, 0x000000d7, +0x000000aa, 0x00000087, 0x0000006b, 0x00000055, 0x00000043, 0x00000035, 0x0000002a, 0x00000021, +0x0000001a, 0x00000015, 0x00000010, 0x0000000d, 0x0000000a, 0x00000008, 0x00000006, 0x00000005, +0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00004924, 0x00003a0d, 0x00002e13, 0x00002492, 0x00001d06, 0x00001709, 0x00001249, 0x00000e83, +0x00000b84, 0x00000924, 0x00000741, 0x000005c2, 0x00000492, 0x000003a0, 0x000002e1, 0x00000249, +0x000001d0, 0x00000170, 0x00000124, 0x000000e8, 0x000000b8, 0x00000092, 0x00000074, 0x0000005c, +0x00000049, 0x0000003a, 0x0000002e, 0x00000024, 0x0000001d, 0x00000017, 0x00000012, 0x0000000e, +0x0000000b, 0x00000009, 0x00000007, 0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000002, +0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00002222, 0x00001b17, 0x00001580, 0x00001111, 0x00000d8b, 0x00000ac0, 0x00000888, 0x000006c5, +0x00000560, 0x00000444, 0x00000362, 0x000002b0, 0x00000222, 0x000001b1, 0x00000158, 0x00000111, +0x000000d8, 0x000000ac, 0x00000088, 0x0000006c, 0x00000056, 0x00000044, 0x00000036, 0x0000002b, +0x00000022, 0x0000001b, 0x00000015, 0x00000011, 0x0000000d, 0x0000000a, 0x00000008, 0x00000006, +0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00001084, 0x00000d1b, 0x00000a67, 0x00000842, 0x0000068d, 0x00000533, 0x00000421, 0x00000346, +0x00000299, 0x00000210, 0x000001a3, 0x0000014c, 0x00000108, 0x000000d1, 0x000000a6, 0x00000084, +0x00000068, 0x00000053, 0x00000042, 0x00000034, 0x00000029, 0x00000021, 0x0000001a, 0x00000014, +0x00000010, 0x0000000d, 0x0000000a, 0x00000008, 0x00000006, 0x00000005, 0x00000004, 0x00000003, +0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000820, 0x00000673, 0x0000051e, 0x00000410, 0x00000339, 0x0000028f, 0x00000208, 0x0000019c, +0x00000147, 0x00000104, 0x000000ce, 0x000000a3, 0x00000082, 0x00000067, 0x00000051, 0x00000041, +0x00000033, 0x00000028, 0x00000020, 0x00000019, 0x00000014, 0x00000010, 0x0000000c, 0x0000000a, +0x00000008, 0x00000006, 0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000001, +0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000408, 0x00000333, 0x0000028a, 0x00000204, 0x00000199, 0x00000145, 0x00000102, 0x000000cc, +0x000000a2, 0x00000081, 0x00000066, 0x00000051, 0x00000040, 0x00000033, 0x00000028, 0x00000020, +0x00000019, 0x00000014, 0x00000010, 0x0000000c, 0x0000000a, 0x00000008, 0x00000006, 0x00000005, +0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000202, 0x00000197, 0x00000143, 0x00000101, 0x000000cb, 0x000000a1, 0x00000080, 0x00000065, +0x00000050, 0x00000040, 0x00000032, 0x00000028, 0x00000020, 0x00000019, 0x00000014, 0x00000010, +0x0000000c, 0x0000000a, 0x00000008, 0x00000006, 0x00000005, 0x00000004, 0x00000003, 0x00000002, +0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000100, 0x000000cb, 0x000000a1, 0x00000080, 0x00000065, 0x00000050, 0x00000040, 0x00000032, +0x00000028, 0x00000020, 0x00000019, 0x00000014, 0x00000010, 0x0000000c, 0x0000000a, 0x00000008, +0x00000006, 0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000001, 0x00000001, +0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000080, 0x00000065, 0x00000050, 0x00000040, 0x00000032, 0x00000028, 0x00000020, 0x00000019, +0x00000014, 0x00000010, 0x0000000c, 0x0000000a, 0x00000008, 0x00000006, 0x00000005, 0x00000004, +0x00000003, 0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000040, 0x00000032, 0x00000028, 0x00000020, 0x00000019, 0x00000014, 0x00000010, 0x0000000c, +0x0000000a, 0x00000008, 0x00000006, 0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000002, +0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000020, 0x00000019, 0x00000014, 0x00000010, 0x0000000c, 0x0000000a, 0x00000008, 0x00000006, +0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000010, 0x0000000c, 0x0000000a, 0x00000008, 0x00000006, 0x00000005, 0x00000004, 0x00000003, +0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000008, 0x00000006, 0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000001, +0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xffff3334, 0xffff5d74, 0xffff7efc, 0xffff999a, 0xffffaeba, 0xffffbf7e, 0xffffcccd, 0xffffd75d, +0xffffdfbf, 0xffffe667, 0xffffebaf, 0xffffefe0, 0xfffff334, 0xfffff5d8, 0xfffff7f0, 0xfffff99a, +0xfffffaec, 0xfffffbf8, 0xfffffccd, 0xfffffd76, 0xfffffdfc, 0xfffffe67, 0xfffffebb, 0xfffffefe, +0xffffff34, 0xffffff5e, 0xffffff7f, 0xffffff9a, 0xffffffaf, 0xffffffc0, 0xffffffcd, 0xffffffd8, +0xffffffe0, 0xffffffe7, 0xffffffec, 0xfffffff0, 0xfffffff4, 0xfffffff6, 0xfffffff8, 0xfffffffa, +0xfffffffb, 0xfffffffc, 0xfffffffd, 0xfffffffe, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xffff999a, 0xffffaeba, 0xffffbf7e, 0xffffcccd, 0xffffd75d, 0xffffdfbf, 0xffffe667, 0xffffebaf, +0xffffefe0, 0xfffff334, 0xfffff5d8, 0xfffff7f0, 0xfffff99a, 0xfffffaec, 0xfffffbf8, 0xfffffccd, +0xfffffd76, 0xfffffdfc, 0xfffffe67, 0xfffffebb, 0xfffffefe, 0xffffff34, 0xffffff5e, 0xffffff7f, +0xffffff9a, 0xffffffaf, 0xffffffc0, 0xffffffcd, 0xffffffd8, 0xffffffe0, 0xffffffe7, 0xffffffec, +0xfffffff0, 0xfffffff4, 0xfffffff6, 0xfffffff8, 0xfffffffa, 0xfffffffb, 0xfffffffc, 0xfffffffd, +0xfffffffe, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00006666, 0x00005146, 0x00004082, 0x00003333, 0x000028a3, 0x00002041, 0x00001999, 0x00001451, +0x00001020, 0x00000ccc, 0x00000a28, 0x00000810, 0x00000666, 0x00000514, 0x00000408, 0x00000333, +0x0000028a, 0x00000204, 0x00000199, 0x00000145, 0x00000102, 0x000000cc, 0x000000a2, 0x00000081, +0x00000066, 0x00000051, 0x00000040, 0x00000033, 0x00000028, 0x00000020, 0x00000019, 0x00000014, +0x00000010, 0x0000000c, 0x0000000a, 0x00000008, 0x00000006, 0x00000005, 0x00000004, 0x00000003, +0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x0000cccc, 0x0000a28c, 0x00008104, 0x00006666, 0x00005146, 0x00004082, 0x00003333, 0x000028a3, +0x00002041, 0x00001999, 0x00001451, 0x00001020, 0x00000ccc, 0x00000a28, 0x00000810, 0x00000666, +0x00000514, 0x00000408, 0x00000333, 0x0000028a, 0x00000204, 0x00000199, 0x00000145, 0x00000102, +0x000000cc, 0x000000a2, 0x00000081, 0x00000066, 0x00000051, 0x00000040, 0x00000033, 0x00000028, +0x00000020, 0x00000019, 0x00000014, 0x00000010, 0x0000000c, 0x0000000a, 0x00000008, 0x00000006, +0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xffff1c72, 0xffff4b64, 0xffff70a7, 0xffff8e39, 0xffffa5b2, 0xffffb854, 0xffffc71d, 0xffffd2d9, +0xffffdc2a, 0xffffe38f, 0xffffe96d, 0xffffee15, 0xfffff1c8, 0xfffff4b7, 0xfffff70b, 0xfffff8e4, +0xfffffa5c, 0xfffffb86, 0xfffffc72, 0xfffffd2e, 0xfffffdc3, 0xfffffe39, 0xfffffe97, 0xfffffee2, +0xffffff1d, 0xffffff4c, 0xffffff71, 0xffffff8f, 0xffffffa6, 0xffffffb9, 0xffffffc8, 0xffffffd3, +0xffffffdd, 0xffffffe4, 0xffffffea, 0xffffffef, 0xfffffff2, 0xfffffff5, 0xfffffff8, 0xfffffff9, +0xfffffffb, 0xfffffffc, 0xfffffffd, 0xfffffffe, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xffff8e39, 0xffffa5b2, 0xffffb854, 0xffffc71d, 0xffffd2d9, 0xffffdc2a, 0xffffe38f, 0xffffe96d, +0xffffee15, 0xfffff1c8, 0xfffff4b7, 0xfffff70b, 0xfffff8e4, 0xfffffa5c, 0xfffffb86, 0xfffffc72, +0xfffffd2e, 0xfffffdc3, 0xfffffe39, 0xfffffe97, 0xfffffee2, 0xffffff1d, 0xffffff4c, 0xffffff71, +0xffffff8f, 0xffffffa6, 0xffffffb9, 0xffffffc8, 0xffffffd3, 0xffffffdd, 0xffffffe4, 0xffffffea, +0xffffffef, 0xfffffff2, 0xfffffff5, 0xfffffff8, 0xfffffff9, 0xfffffffb, 0xfffffffc, 0xfffffffd, +0xfffffffe, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xffffc71d, 0xffffd2d9, 0xffffdc2a, 0xffffe38f, 0xffffe96d, 0xffffee15, 0xfffff1c8, 0xfffff4b7, +0xfffff70b, 0xfffff8e4, 0xfffffa5c, 0xfffffb86, 0xfffffc72, 0xfffffd2e, 0xfffffdc3, 0xfffffe39, +0xfffffe97, 0xfffffee2, 0xffffff1d, 0xffffff4c, 0xffffff71, 0xffffff8f, 0xffffffa6, 0xffffffb9, +0xffffffc8, 0xffffffd3, 0xffffffdd, 0xffffffe4, 0xffffffea, 0xffffffef, 0xfffffff2, 0xfffffff5, +0xfffffff8, 0xfffffff9, 0xfffffffb, 0xfffffffc, 0xfffffffd, 0xfffffffe, 0xfffffffe, 0xffffffff, +0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x000038e3, 0x00002d27, 0x000023d6, 0x00001c71, 0x00001693, 0x000011eb, 0x00000e38, 0x00000b49, +0x000008f5, 0x0000071c, 0x000005a4, 0x0000047a, 0x0000038e, 0x000002d2, 0x0000023d, 0x000001c7, +0x00000169, 0x0000011e, 0x000000e3, 0x000000b4, 0x0000008f, 0x00000071, 0x0000005a, 0x00000047, +0x00000038, 0x0000002d, 0x00000023, 0x0000001c, 0x00000016, 0x00000011, 0x0000000e, 0x0000000b, +0x00000008, 0x00000007, 0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000001, +0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x000071c7, 0x00005a4e, 0x000047ac, 0x000038e3, 0x00002d27, 0x000023d6, 0x00001c71, 0x00001693, +0x000011eb, 0x00000e38, 0x00000b49, 0x000008f5, 0x0000071c, 0x000005a4, 0x0000047a, 0x0000038e, +0x000002d2, 0x0000023d, 0x000001c7, 0x00000169, 0x0000011e, 0x000000e3, 0x000000b4, 0x0000008f, +0x00000071, 0x0000005a, 0x00000047, 0x00000038, 0x0000002d, 0x00000023, 0x0000001c, 0x00000016, +0x00000011, 0x0000000e, 0x0000000b, 0x00000008, 0x00000007, 0x00000005, 0x00000004, 0x00000003, +0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x0000e38e, 0x0000b49c, 0x00008f59, 0x000071c7, 0x00005a4e, 0x000047ac, 0x000038e3, 0x00002d27, +0x000023d6, 0x00001c71, 0x00001693, 0x000011eb, 0x00000e38, 0x00000b49, 0x000008f5, 0x0000071c, +0x000005a4, 0x0000047a, 0x0000038e, 0x000002d2, 0x0000023d, 0x000001c7, 0x00000169, 0x0000011e, +0x000000e3, 0x000000b4, 0x0000008f, 0x00000071, 0x0000005a, 0x00000047, 0x00000038, 0x0000002d, +0x00000023, 0x0000001c, 0x00000016, 0x00000011, 0x0000000e, 0x0000000b, 0x00000008, 0x00000007, +0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_gainpow2_data[] = { +0x05a82799, 0x04c1bf82, 0x04000000, 0x035d13f3, 0x02d413cc, 0x0260dfc1, 0x02000000, 0x01ae89f9, +0x016a09e6, 0x01306fe0, 0x01000000, 0x00d744fc, 0x00b504f3, 0x009837f0, 0x00800000, 0x006ba27e, +0x005a8279, 0x004c1bf8, 0x00400000, 0x0035d13f, 0x002d413c, 0x00260dfc, 0x00200000, 0x001ae89f, +0x0016a09e, 0x001306fe, 0x00100000, 0x000d744f, 0x000b504f, 0x0009837f, 0x00080000, 0x0006ba27, +0x0005a827, 0x0004c1bf, 0x00040000, 0x00035d13, 0x0002d413, 0x000260df, 0x00020000, 0x0001ae89, +0x00016a09, 0x0001306f, 0x00010000, 0x0000d744, 0x0000b504, 0x00009837, 0x00008000, 0x00006ba2, +0x00005a82, 0x00004c1b, 0x00004000, 0x000035d1, 0x00002d41, 0x0000260d, 0x00002000, 0x00001ae8, +0x000016a0, 0x00001306, 0x00001000, 0x00000d74, 0x00000b50, 0x00000983, 0x00000800, 0x000006ba, +0x000005a8, 0x000004c1, 0x00000400, 0x0000035d, 0x000002d4, 0x00000260, 0x00000200, 0x000001ae, +0x0000016a, 0x00000130, 0x00000100, 0x000000d7, 0x000000b5, 0x00000098, 0x00000080, 0x0000006b, +0x0000005a, 0x0000004c, 0x00000040, 0x00000035, 0x0000002d, 0x00000026, 0x00000020, 0x0000001a, +0x00000016, 0x00000013, 0x00000010, 0x0000000d, 0x0000000b, 0x00000009, 0x00000008, 0x00000006, +0x00000005, 0x00000004, 0x00000004, 0x00000003, 0x00000002, 0x00000002, 0x00000002, 0x00000001, +0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_ispow_data[] = { +0x00000000, 0x00008000, 0x0001428a, 0x000229d2, 0x00032cbf, 0x00044662, 0x0005738c, 0x0006b1fc, +0x0007ffff, 0x00095c41, 0x000ac5ad, 0x000c3b5d, 0x000dbc8f, 0x000f489e, 0x0010def9, 0x00127f20, +0x001428a2, 0x0015db1b, 0x00179630, 0x0019598d, 0x001b24e8, 0x001cf7fc, 0x001ed28a, 0x0020b458, +0x00229d2e, 0x00248cdb, 0x0026832f, 0x00287fff, 0x002a8322, 0x002c8c70, 0x002e9bc5, 0x0030b0ff, +0x0032cbfd, 0x0034eca0, 0x003712ca, 0x00393e60, 0x003b6f47, 0x003da567, 0x003fe0a5, 0x004220ed, +0x00446627, 0x0046b03e, 0x0048ff1e, 0x004b52b3, 0x004daaeb, 0x005007b4, 0x005268fc, 0x0054ceb2, +0x005738c7, 0x0059a72a, 0x005c19cd, 0x005e90a1, 0x00610b98, 0x00638aa4, 0x00660db9, 0x006894c9, +0x006b1fc8, 0x006daeaa, 0x00704163, 0x0072d7e8, 0x0075722e, 0x0078102b, 0x007ab1d3, 0x007d571e, +0x007fffff, 0x0082ac70, 0x00855c65, 0x00880fd6, 0x008ac6b9, 0x008d8107, 0x00903eb7, 0x0092ffc0, +0x0095c41a, 0x00988bbe, 0x009b56a4, 0x009e24c4, 0x00a0f617, 0x00a3ca96, 0x00a6a239, 0x00a97cfa, +0x00ac5ad2, 0x00af3bbb, 0x00b21fad, 0x00b506a3, 0x00b7f096, 0x00badd81, 0x00bdcd5d, 0x00c0c025, +0x00c3b5d2, 0x00c6ae60, 0x00c9a9c8, 0x00cca805, 0x00cfa912, 0x00d2acea, 0x00d5b387, 0x00d8bce5, +0x00dbc8fe, 0x00ded7ce, 0x00e1e950, 0x00e4fd7e, 0x00e81456, 0x00eb2dd1, 0x00ee49ec, 0x00f168a2, +0x00f489ef, 0x00f7adce, 0x00fad43c, 0x00fdfd34, 0x010128b2, 0x010456b2, 0x01078731, 0x010aba29, +0x010def99, 0x0111277b, 0x011461cc, 0x01179e89, 0x011addae, 0x011e1f37, 0x01216320, 0x0124a967, +0x0127f208, 0x012b3d00, 0x012e8a4b, 0x0131d9e6, 0x01352bce, 0x01387fff, 0x013bd678, 0x013f2f33, +0x01428a2f, 0x0145e768, 0x014946dc, 0x014ca888, 0x01500c68, 0x01537279, 0x0156daba, 0x015a4527, +0x015db1bd, 0x0161207a, 0x0164915b, 0x0168045d, 0x016b797e, 0x016ef0bb, 0x01726a12, 0x0175e580, +0x01796302, 0x017ce297, 0x0180643b, 0x0183e7ec, 0x01876da9, 0x018af56e, 0x018e7f38, 0x01920b07, +0x019598d8, 0x019928a8, 0x019cba74, 0x01a04e3c, 0x01a3e3fd, 0x01a77bb4, 0x01ab155f, 0x01aeb0fd, +0x01b24e8b, 0x01b5ee07, 0x01b98f70, 0x01bd32c2, 0x01c0d7fc, 0x01c47f1d, 0x01c82821, 0x01cbd308, +0x01cf7fcf, 0x01d32e74, 0x01d6def6, 0x01da9153, 0x01de4588, 0x01e1fb94, 0x01e5b375, 0x01e96d29, +0x01ed28af, 0x01f0e604, 0x01f4a528, 0x01f86617, 0x01fc28d2, 0x01ffed55, 0x0203b39f, 0x02077baf, +0x020b4582, 0x020f1118, 0x0212de6e, 0x0216ad83, 0x021a7e56, 0x021e50e4, 0x0222252d, 0x0225fb2e, +0x0229d2e6, 0x022dac54, 0x02318776, 0x0235644b, 0x023942d1, 0x023d2306, 0x024104e9, 0x0244e879, +0x0248cdb5, 0x024cb49a, 0x02509d28, 0x0254875c, 0x02587337, 0x025c60b5, 0x02604fd7, 0x0264409a, +0x026832fd, 0x026c26ff, 0x02701c9f, 0x027413db, 0x02780cb1, 0x027c0722, 0x0280032a, 0x028400ca, +0x0287ffff, 0x028c00ca, 0x02900327, 0x02940716, 0x02980c97, 0x029c13a7, 0x02a01c45, 0x02a42670, +0x02a83228, 0x02ac3f6a, 0x02b04e36, 0x02b45e8b, 0x02b87067, 0x02bc83c9, 0x02c098b1, 0x02c4af1c, +0x02c8c70a, 0x02cce07a, 0x02d0fb6a, 0x02d517da, 0x02d935c9, 0x02dd5534, 0x02e1761c, 0x02e59880, +0x02e9bc5d, 0x02ede1b3, 0x02f20882, 0x02f630c8, 0x02fa5a83, 0x02fe85b4, 0x0302b258, 0x0306e070, +0x030b0ff9, 0x030f40f3, 0x0313735e, 0x0317a737, 0x031bdc7e, 0x03201333, 0x03244b53, 0x032884de, +0x032cbfd4, 0x0330fc33, 0x033539fa, 0x03397929, 0x033db9be, 0x0341fbb8, 0x03463f17, 0x034a83da, +0x034eca00, 0x03531187, 0x03575a6f, 0x035ba4b8, 0x035ff060, 0x03643d66, 0x03688bc9, 0x036cdb8a, +0x03712ca6, 0x03757f1d, 0x0379d2ee, 0x037e2818, 0x03827e9a, 0x0386d674, 0x038b2fa5, 0x038f8a2c, +0x0393e608, 0x03984338, 0x039ca1bc, 0x03a10192, 0x03a562ba, 0x03a9c533, 0x03ae28fd, 0x03b28e16, +0x03b6f47e, 0x03bb5c33, 0x03bfc536, 0x03c42f85, 0x03c89b20, 0x03cd0806, 0x03d17636, 0x03d5e5af, +0x03da5671, 0x03dec87b, 0x03e33bcc, 0x03e7b063, 0x03ec2640, 0x03f09d62, 0x03f515c9, 0x03f98f73, +0x03fe0a5f, 0x0402868e, 0x040703fe, 0x040b82af, 0x041002a0, 0x041483d1, 0x04190640, 0x041d89ec, +0x04220ed7, 0x042694fd, 0x042b1c60, 0x042fa4fe, 0x04342ed6, 0x0438b9e9, 0x043d4635, 0x0441d3b9, +0x04466275, 0x044af269, 0x044f8393, 0x045415f3, 0x0458a988, 0x045d3e53, 0x0461d451, 0x04666b83, +0x046b03e7, 0x046f9d7e, 0x04743846, 0x0478d440, 0x047d716a, 0x04820fc3, 0x0486af4c, 0x048b5003, +0x048ff1e8, 0x049494fa, 0x04993939, 0x049ddea5, 0x04a2853c, 0x04a72cfd, 0x04abd5ea, 0x04b07fff, +0x04b52b3f, 0x04b9d7a6, 0x04be8536, 0x04c333ee, 0x04c7e3cc, 0x04cc94d1, 0x04d146fb, 0x04d5fa4b, +0x04daaebf, 0x04df6458, 0x04e41b14, 0x04e8d2f3, 0x04ed8bf5, 0x04f24618, 0x04f7015d, 0x04fbbdc3, +0x05007b49, 0x050539ef, 0x0509f9b4, 0x050eba98, 0x05137c9a, 0x05183fba, 0x051d03f6, 0x0521c950, +0x05268fc6, 0x052b5757, 0x05302003, 0x0534e9ca, 0x0539b4ab, 0x053e80a5, 0x05434db9, 0x05481be5, +0x054ceb29, 0x0551bb85, 0x05568cf8, 0x055b5f81, 0x05603321, 0x056507d6, 0x0569dda0, 0x056eb47f, +0x05738c72, 0x05786578, 0x057d3f92, 0x05821abe, 0x0586f6fd, 0x058bd44e, 0x0590b2af, 0x05959222, +0x059a72a5, 0x059f5438, 0x05a436da, 0x05a91a8c, 0x05adff4b, 0x05b2e519, 0x05b7cbf5, 0x05bcb3dd, +0x05c19cd3, 0x05c686d4, 0x05cb71e2, 0x05d05dfb, 0x05d54b1f, 0x05da394d, 0x05df2885, 0x05e418c7, +0x05e90a12, 0x05edfc66, 0x05f2efc2, 0x05f7e426, 0x05fcd992, 0x0601d004, 0x0606c77d, 0x060bbffd, +0x0610b982, 0x0615b40c, 0x061aaf9b, 0x061fac2f, 0x0624a9c7, 0x0629a863, 0x062ea802, 0x0633a8a3, +0x0638aa47, 0x063dacee, 0x0642b095, 0x0647b53f, 0x064cbae8, 0x0651c193, 0x0656c93d, 0x065bd1e7, +0x0660db90, 0x0665e639, 0x066af1df, 0x066ffe84, 0x06750c26, 0x067a1ac6, 0x067f2a62, 0x06843afb, +0x06894c90, 0x068e5f21, 0x069372ad, 0x06988735, 0x069d9cb6, 0x06a2b332, 0x06a7caa8, 0x06ace318, +0x06b1fc80, 0x06b716e2, 0x06bc323b, 0x06c14e8d, 0x06c66bd6, 0x06cb8a17, 0x06d0a94e, 0x06d5c97c, +0x06daeaa0, 0x06e00cba, 0x06e52fca, 0x06ea53ce, 0x06ef78c8, 0x06f49eb5, 0x06f9c597, 0x06feed6d, +0x07041635, 0x07093ff1, 0x070e6aa0, 0x07139640, 0x0718c2d3, 0x071df057, 0x07231ecd, 0x07284e33, +0x072d7e8a, 0x0732afd2, 0x0737e209, 0x073d1530, 0x07424946, 0x07477e4a, 0x074cb43e, 0x0751eb20, +0x075722ef, 0x075c5bac, 0x07619556, 0x0766cfee, 0x076c0b71, 0x077147e1, 0x0776853d, 0x077bc385, +0x078102b8, 0x078642d6, 0x078b83de, 0x0790c5d1, 0x079608ae, 0x079b4c74, 0x07a09124, 0x07a5d6bd, +0x07ab1d3e, 0x07b064a8, 0x07b5acfa, 0x07baf634, 0x07c04056, 0x07c58b5e, 0x07cad74e, 0x07d02424, +0x07d571e0, 0x07dac082, 0x07e0100a, 0x07e56077, 0x07eab1ca, 0x07f00401, 0x07f5571c, 0x07faab1c, +0x07ffffff, 0x080555c7, 0x080aac71, 0x081003fe, 0x08155c6e, 0x081ab5c0, 0x08200ff5, 0x08256b0b, +0x082ac703, 0x083023dc, 0x08358196, 0x083ae030, 0x08403fab, 0x0845a006, 0x084b0141, 0x0850635b, +0x0855c654, 0x085b2a2d, 0x08608ee4, 0x0865f479, 0x086b5aed, 0x0870c23e, 0x08762a6d, 0x087b9379, +0x0880fd62, 0x08866828, 0x088bd3ca, 0x08914048, 0x0896ada3, 0x089c1bd8, 0x08a18aea, 0x08a6fad6, +0x08ac6b9d, 0x08b1dd3f, 0x08b74fbb, 0x08bcc311, 0x08c23741, 0x08c7ac4a, 0x08cd222c, 0x08d298e8, +0x08d8107c, 0x08dd88e8, 0x08e3022d, 0x08e87c49, 0x08edf73d, 0x08f37309, 0x08f8efac, 0x08fe6d25, +0x0903eb75, 0x09096a9c, 0x090eea99, 0x09146b6b, 0x0919ed13, 0x091f6f91, 0x0924f2e3, 0x092a770b, +0x092ffc06, 0x093581d7, 0x093b087b, 0x09408ff3, 0x0946183f, 0x094ba15e, 0x09512b51, 0x0956b616, +0x095c41ae, 0x0961ce18, 0x09675b54, 0x096ce962, 0x09727842, 0x097807f3, 0x097d9876, 0x098329c9, +0x0988bbed, 0x098e4ee1, 0x0993e2a6, 0x0999773a, 0x099f0c9f, 0x09a4a2d3, 0x09aa39d6, 0x09afd1a8, +0x09b56a49, 0x09bb03b8, 0x09c09df6, 0x09c63902, 0x09cbd4dc, 0x09d17183, 0x09d70ef8, 0x09dcad3a, +0x09e24c49, 0x09e7ec25, 0x09ed8ccd, 0x09f32e41, 0x09f8d082, 0x09fe738e, 0x0a041766, 0x0a09bc09, +0x0a0f6178, 0x0a1507b1, 0x0a1aaeb5, 0x0a205684, 0x0a25ff1c, 0x0a2ba87f, 0x0a3152ac, 0x0a36fda2, +0x0a3ca962, 0x0a4255ea, 0x0a48033c, 0x0a4db157, 0x0a536039, 0x0a590fe5, 0x0a5ec058, 0x0a647193, +0x0a6a2396, 0x0a6fd660, 0x0a7589f2, 0x0a7b3e4b, 0x0a80f36a, 0x0a86a950, 0x0a8c5ffc, 0x0a92176f, +0x0a97cfa7, 0x0a9d88a5, 0x0aa34269, 0x0aa8fcf2, 0x0aaeb840, 0x0ab47453, 0x0aba312b, 0x0abfeec8, +0x0ac5ad28, 0x0acb6c4d, 0x0ad12c36, 0x0ad6ece2, 0x0adcae52, 0x0ae27085, 0x0ae8337b, 0x0aedf734, +0x0af3bbb0, 0x0af980ee, 0x0aff46ef, 0x0b050db2, 0x0b0ad536, 0x0b109d7c, 0x0b166684, 0x0b1c304d, +0x0b21fad7, 0x0b27c622, 0x0b2d922e, 0x0b335efa, 0x0b392c87, 0x0b3efad3, 0x0b44c9e0, 0x0b4a99ac, +0x0b506a38, 0x0b563b83, 0x0b5c0d8e, 0x0b61e057, 0x0b67b3df, 0x0b6d8826, 0x0b735d2b, 0x0b7932ee, +0x0b7f096f, 0x0b84e0ae, 0x0b8ab8ab, 0x0b909165, 0x0b966add, 0x0b9c4511, 0x0ba22003, 0x0ba7fbb1, +0x0badd81b, 0x0bb3b542, 0x0bb99326, 0x0bbf71c5, 0x0bc55120, 0x0bcb3136, 0x0bd11208, 0x0bd6f395, +0x0bdcd5dd, 0x0be2b8e0, 0x0be89c9e, 0x0bee8116, 0x0bf46649, 0x0bfa4c36, 0x0c0032dc, 0x0c061a3d, +0x0c0c0257, 0x0c11eb2a, 0x0c17d4b7, 0x0c1dbefd, 0x0c23a9fc, 0x0c2995b3, 0x0c2f8223, 0x0c356f4c, +0x0c3b5d2c, 0x0c414bc5, 0x0c473b16, 0x0c4d2b1e, 0x0c531bde, 0x0c590d55, 0x0c5eff83, 0x0c64f268, +0x0c6ae604, 0x0c70da57, 0x0c76cf60, 0x0c7cc51f, 0x0c82bb95, 0x0c88b2c1, 0x0c8eaaa2, 0x0c94a339, +0x0c9a9c85, 0x0ca09687, 0x0ca6913e, 0x0cac8caa, 0x0cb288ca, 0x0cb885a0, 0x0cbe8329, 0x0cc48167, +0x0cca8059, 0x0cd07fff, 0x0cd68059, 0x0cdc8167, 0x0ce28328, 0x0ce8859c, 0x0cee88c4, 0x0cf48c9e, +0x0cfa912b, 0x0d00966b, 0x0d069c5d, 0x0d0ca302, 0x0d12aa59, 0x0d18b262, 0x0d1ebb1d, 0x0d24c489, +0x0d2acea7, 0x0d30d976, 0x0d36e4f7, 0x0d3cf128, 0x0d42fe0b, 0x0d490b9e, 0x0d4f19e2, 0x0d5528d6, +0x0d5b387b, 0x0d6148cf, 0x0d6759d4, 0x0d6d6b88, 0x0d737dec, 0x0d799100, 0x0d7fa4c3, 0x0d85b935, +0x0d8bce56, 0x0d91e426, 0x0d97faa4, 0x0d9e11d1, 0x0da429ad, 0x0daa4237, 0x0db05b6f, 0x0db67555, +0x0dbc8fe9, 0x0dc2ab2a, 0x0dc8c719, 0x0dcee3b5, 0x0dd500ff, 0x0ddb1ef5, 0x0de13d99, 0x0de75ce9, +0x0ded7ce6, 0x0df39d8f, 0x0df9bee5, 0x0dffe0e7, 0x0e060394, 0x0e0c26ee, 0x0e124af4, 0x0e186fa5, +0x0e1e9501, 0x0e24bb09, 0x0e2ae1bb, 0x0e310919, 0x0e373122, 0x0e3d59d5, 0x0e438333, 0x0e49ad3c, +0x0e4fd7ee, 0x0e56034b, 0x0e5c2f52, 0x0e625c02, 0x0e68895d, 0x0e6eb761, 0x0e74e60e, 0x0e7b1564, +0x0e814564, 0x0e87760d, 0x0e8da75e, 0x0e93d959, 0x0e9a0bfb, 0x0ea03f47, 0x0ea6733a, 0x0eaca7d6, +0x0eb2dd1a, 0x0eb91305, 0x0ebf4999, 0x0ec580d4, 0x0ecbb8b6, 0x0ed1f140, 0x0ed82a71, 0x0ede6449, +0x0ee49ec8, 0x0eead9ed, 0x0ef115ba, 0x0ef7522d, 0x0efd8f46, 0x0f03cd05, 0x0f0a0b6b, 0x0f104a76, +0x0f168a28, 0x0f1cca7f, 0x0f230b7b, 0x0f294d1d, 0x0f2f8f65, 0x0f35d251, 0x0f3c15e3, 0x0f425a19, +0x0f489ef4, 0x0f4ee474, 0x0f552a98, 0x0f5b7161, 0x0f61b8ce, 0x0f6800df, 0x0f6e4994, 0x0f7492ed, +0x0f7adce9, 0x0f81278a, 0x0f8772cd, 0x0f8dbeb4, 0x0f940b3e, 0x0f9a586b, 0x0fa0a63c, 0x0fa6f4af, +0x0fad43c4, 0x0fb3937c, 0x0fb9e3d7, 0x0fc034d4, 0x0fc68673, 0x0fccd8b4, 0x0fd32b97, 0x0fd97f1c, +0x0fdfd343, 0x0fe6280b, 0x0fec7d74, 0x0ff2d37f, 0x0ff92a2b, 0x0fff8178, 0x1005d966, 0x100c31f5, +0x10128b24, 0x1018e4f4, 0x101f3f64, 0x10259a75, 0x102bf626, 0x10325277, 0x1038af67, 0x103f0cf8, +0x10456b28, 0x104bc9f8, 0x10522967, 0x10588976, 0x105eea24, 0x10654b70, 0x106bad5c, 0x10720fe7, +0x10787310, 0x107ed6d8, 0x10853b3f, 0x108ba043, 0x109205e6, 0x10986c27, 0x109ed307, 0x10a53a83, +0x10aba29e, 0x10b20b57, 0x10b874ac, 0x10bedea0, 0x10c54930, 0x10cbb45e, 0x10d22029, 0x10d88c90, +0x10def995, 0x10e56736, 0x10ebd574, 0x10f2444e, 0x10f8b3c5, 0x10ff23d8, 0x11059487, 0x110c05d2, +0x111277b9, 0x1118ea3b, 0x111f5d59, 0x1125d113, 0x112c4568, 0x1132ba59, 0x11392fe5, 0x113fa60c, +0x11461ccd, 0x114c942a, 0x11530c22, 0x115984b4, 0x115ffde0, 0x116677a7, 0x116cf209, 0x11736d04, +0x1179e89a, 0x118064c9, 0x1186e192, 0x118d5ef5, 0x1193dcf2, 0x119a5b88, 0x11a0dab8, 0x11a75a81, +0x11addae3, 0x11b45bde, 0x11badd72, 0x11c15f9f, 0x11c7e265, 0x11ce65c4, 0x11d4e9bb, 0x11db6e4a, +0x11e1f372, 0x11e87931, 0x11eeff89, 0x11f58679, 0x11fc0e01, 0x12029621, 0x12091ed8, 0x120fa827, +0x1216320d, 0x121cbc8a, 0x1223479f, 0x1229d34b, 0x12305f8e, 0x1236ec68, 0x123d79d9, 0x124407e0, +0x124a967e, 0x125125b2, 0x1257b57d, 0x125e45de, 0x1264d6d6, 0x126b6863, 0x1271fa86, 0x12788d40, +0x127f208f, 0x1285b473, 0x128c48ed, 0x1292ddfd, 0x129973a2, 0x12a009dc, 0x12a6a0ab, 0x12ad3810, +0x12b3d009, 0x12ba6897, 0x12c101ba, 0x12c79b71, 0x12ce35bd, 0x12d4d09e, 0x12db6c13, 0x12e2081b, +0x12e8a4b9, 0x12ef41ea, 0x12f5dfaf, 0x12fc7e07, 0x13031cf4, 0x1309bc74, 0x13105c88, 0x1316fd2f, +0x131d9e69, 0x13244036, 0x132ae297, 0x1331858b, 0x13382911, 0x133ecd2b, 0x134571d7, 0x134c1716, +0x1352bce7, 0x1359634a, 0x13600a40, 0x1366b1c9, 0x136d59e3, 0x1374028f, 0x137aabce, 0x1381559e, +0x1387ffff, 0x138eaaf3, 0x13955678, 0x139c028e, 0x13a2af36, 0x13a95c6f, 0x13b00a39, 0x13b6b895, +0x13bd6781, 0x13c416fe, 0x13cac70c, 0x13d177aa, 0x13d828d9, 0x13deda99, 0x13e58ce9, 0x13ec3fc9, +0x13f2f33a, 0x13f9a73a, 0x14005bcb, 0x140710eb, 0x140dc69c, 0x14147cdc, 0x141b33ab, 0x1421eb0a, +0x1428a2f9, 0x142f5b77, 0x14361484, 0x143cce21, 0x1443884c, 0x144a4307, 0x1450fe50, 0x1457ba28, +0x145e768f, 0x14653384, 0x146bf108, 0x1472af1b, 0x14796dbb, 0x14802cea, 0x1486eca8, 0x148dacf3, +0x14946dcc, 0x149b2f33, 0x14a1f128, 0x14a8b3aa, 0x14af76ba, 0x14b63a58, 0x14bcfe83, 0x14c3c33b, +0x14ca8881, 0x14d14e54, 0x14d814b4, 0x14dedba0, 0x14e5a31a, 0x14ec6b21, 0x14f333b4, 0x14f9fcd4, +0x1500c680, 0x150790b9, 0x150e5b7e, 0x151526cf, 0x151bf2ad, 0x1522bf17, 0x15298c0c, 0x1530598e, +0x1537279b, 0x153df634, 0x1544c559, 0x154b950a, 0x15526545, 0x1559360d, 0x1560075f, 0x1566d93d, +0x156daba6, 0x15747e99, 0x157b5218, 0x15822622, 0x1588fab6, 0x158fcfd6, 0x1596a57f, 0x159d7bb4, +0x15a45272, 0x15ab29bc, 0x15b2018f, 0x15b8d9ed, 0x15bfb2d4, 0x15c68c46, 0x15cd6641, 0x15d440c7, +0x15db1bd6, 0x15e1f76f, 0x15e8d391, 0x15efb03d, 0x15f68d73, 0x15fd6b31, 0x16044979, 0x160b284a, +0x161207a5, 0x1618e788, 0x161fc7f4, 0x1626a8e9, 0x162d8a67, 0x16346c6d, 0x163b4efc, 0x16423213, +0x164915b3, 0x164ff9dc, 0x1656de8c, 0x165dc3c5, 0x1664a985, 0x166b8fce, 0x1672769f, 0x16795df7, +0x168045d8, 0x16872e40, 0x168e172f, 0x169500a7, 0x169beaa5, 0x16a2d52b, 0x16a9c038, 0x16b0abcd, +0x16b797e8, 0x16be848b, 0x16c571b4, 0x16cc5f65, 0x16d34d9c, 0x16da3c5a, 0x16e12b9e, 0x16e81b69, +0x16ef0bbb, 0x16f5fc93, 0x16fcedf1, 0x1703dfd6, 0x170ad241, 0x1711c531, 0x1718b8a8, 0x171faca5, +0x1726a127, 0x172d9630, 0x17348bbe, 0x173b81d1, 0x1742786b, 0x17496f89, 0x1750672d, 0x17575f56, +0x175e5805, 0x17655139, 0x176c4af1, 0x1773452f, 0x177a3ff2, 0x17813b39, 0x17883705, 0x178f3356, +0x1796302c, 0x179d2d86, 0x17a42b64, 0x17ab29c7, 0x17b228ae, 0x17b92819, 0x17c02809, 0x17c7287c, +0x17ce2974, 0x17d52aef, 0x17dc2cef, 0x17e32f72, 0x17ea3278, 0x17f13603, 0x17f83a11, 0x17ff3ea2, +0x180643b7, 0x180d494f, 0x18144f6a, 0x181b5609, 0x18225d2a, 0x182964cf, 0x18306cf6, 0x183775a1, +0x183e7ece, 0x1845887e, 0x184c92b0, 0x18539d65, 0x185aa89d, 0x1861b457, 0x1868c093, 0x186fcd52, +0x1876da93, 0x187de856, 0x1884f69b, 0x188c0562, 0x189314aa, 0x189a2475, 0x18a134c2, 0x18a84590, +0x18af56e0, 0x18b668b1, 0x18bd7b04, 0x18c48dd8, 0x18cba12d, 0x18d2b504, 0x18d9c95c, 0x18e0de35, +0x18e7f38f, 0x18ef096b, 0x18f61fc7, 0x18fd36a3, 0x19044e01, 0x190b65df, 0x19127e3e, 0x1919971d, +0x1920b07d, 0x1927ca5d, 0x192ee4be, 0x1935ff9f, 0x193d1b00, 0x194436e1, 0x194b5342, 0x19527023, +0x19598d84, 0x1960ab65, 0x1967c9c6, 0x196ee8a6, 0x19760806, 0x197d27e6, 0x19844845, 0x198b6923, +0x19928a81, 0x1999ac5e, 0x19a0ceba, 0x19a7f196, 0x19af14f0, 0x19b638ca, 0x19bd5d22, 0x19c481f9, +0x19cba74f, 0x19d2cd24, 0x19d9f378, 0x19e11a4a, 0x19e8419a, 0x19ef6969, 0x19f691b6, 0x19fdba82, +0x1a04e3cc, 0x1a0c0d94, 0x1a1337da, 0x1a1a629f, 0x1a218de1, 0x1a28b9a1, 0x1a2fe5df, 0x1a37129b, +0x1a3e3fd4, 0x1a456d8b, 0x1a4c9bc0, 0x1a53ca72, 0x1a5af9a2, 0x1a62294f, 0x1a695979, 0x1a708a21, +0x1a77bb45, 0x1a7eece7, 0x1a861f06, 0x1a8d51a2, 0x1a9484bb, 0x1a9bb850, 0x1aa2ec62, 0x1aaa20f1, +0x1ab155fd, 0x1ab88b85, 0x1abfc18a, 0x1ac6f80b, 0x1ace2f09, 0x1ad56683, 0x1adc9e79, 0x1ae3d6eb, +0x1aeb0fda, 0x1af24944, 0x1af9832b, 0x1b00bd8d, 0x1b07f86c, 0x1b0f33c6, 0x1b166f9c, 0x1b1dabed, +0x1b24e8ba, 0x1b2c2603, 0x1b3363c7, 0x1b3aa206, 0x1b41e0c1, 0x1b491ff7, 0x1b505fa9, 0x1b579fd5, +0x1b5ee07d, 0x1b66219f, 0x1b6d633d, 0x1b74a555, 0x1b7be7e9, 0x1b832af7, 0x1b8a6e7f, 0x1b91b283, +0x1b98f701, 0x1ba03bf9, 0x1ba7816c, 0x1baec75a, 0x1bb60dc1, 0x1bbd54a3, 0x1bc49bff, 0x1bcbe3d6, +0x1bd32c26, 0x1bda74f1, 0x1be1be35, 0x1be907f3, 0x1bf0522b, 0x1bf79cdd, 0x1bfee809, 0x1c0633ae, +0x1c0d7fcc, 0x1c14cc65, 0x1c1c1976, 0x1c236702, 0x1c2ab506, 0x1c320384, 0x1c39527b, 0x1c40a1eb, +0x1c47f1d4, 0x1c4f4236, 0x1c569311, 0x1c5de466, 0x1c653632, 0x1c6c8878, 0x1c73db37, 0x1c7b2e6e, +0x1c82821d, 0x1c89d646, 0x1c912ae6, 0x1c987fff, 0x1c9fd591, 0x1ca72b9b, 0x1cae821d, 0x1cb5d917, +0x1cbd3089, 0x1cc48874, 0x1ccbe0d6, 0x1cd339b1, 0x1cda9303, 0x1ce1eccd, 0x1ce9470f, 0x1cf0a1c8, +0x1cf7fcf9, 0x1cff58a2, 0x1d06b4c2, 0x1d0e115a, 0x1d156e69, 0x1d1ccbf0, 0x1d2429ed, 0x1d2b8862, +0x1d32e74e, 0x1d3a46b2, 0x1d41a68c, 0x1d4906dd, 0x1d5067a6, 0x1d57c8e5, 0x1d5f2a9b, 0x1d668cc7, +0x1d6def6b, 0x1d755285, 0x1d7cb615, 0x1d841a1c, 0x1d8b7e9a, 0x1d92e38e, 0x1d9a48f9, 0x1da1aed9, +0x1da91530, 0x1db07bfd, 0x1db7e340, 0x1dbf4afa, 0x1dc6b329, 0x1dce1bce, 0x1dd584e9, 0x1ddcee7a, +0x1de45881, 0x1debc2fe, 0x1df32df0, 0x1dfa9957, 0x1e020535, 0x1e097187, 0x1e10de50, 0x1e184b8d, +0x1e1fb940, 0x1e272768, 0x1e2e9606, 0x1e360518, 0x1e3d74a0, 0x1e44e49d, 0x1e4c550e, 0x1e53c5f5, +0x1e5b3750, 0x1e62a921, 0x1e6a1b66, 0x1e718e20, 0x1e79014e, 0x1e8074f1, 0x1e87e909, 0x1e8f5d95, +0x1e96d295, 0x1e9e480a, 0x1ea5bdf3, 0x1ead3450, 0x1eb4ab22, 0x1ebc2268, 0x1ec39a22, 0x1ecb1250, +0x1ed28af1, 0x1eda0407, 0x1ee17d91, 0x1ee8f78f, 0x1ef07200, 0x1ef7ece5, 0x1eff683d, 0x1f06e40a, +0x1f0e604a, 0x1f15dcfd, 0x1f1d5a24, 0x1f24d7be, 0x1f2c55cb, 0x1f33d44c, 0x1f3b5340, 0x1f42d2a7, +0x1f4a5281, 0x1f51d2ce, 0x1f59538f, 0x1f60d4c2, 0x1f685668, 0x1f6fd881, 0x1f775b0d, 0x1f7ede0c, +0x1f86617d, 0x1f8de561, 0x1f9569b7, 0x1f9cee80, 0x1fa473bb, 0x1fabf969, 0x1fb37f8a, 0x1fbb061c, +0x1fc28d21, 0x1fca1498, 0x1fd19c81, 0x1fd924dc, 0x1fe0ada9, 0x1fe836e9, 0x1fefc09a, 0x1ff74abd, +0x1ffed552, 0x20066059, 0x200debd1, 0x201577bc, 0x201d0417, 0x202490e5, 0x202c1e24, 0x2033abd4, +0x203b39f6, 0x2042c889, 0x204a578d, 0x2051e703, 0x205976ea, 0x20610742, 0x2068980b, 0x20702946, +0x2077baf1, 0x207f4d0d, 0x2086df9a, 0x208e7298, 0x20960607, 0x209d99e7, 0x20a52e37, 0x20acc2f8, +0x20b45829, 0x20bbedcb, 0x20c383de, 0x20cb1a61, 0x20d2b154, 0x20da48b8, 0x20e1e08c, 0x20e978d0, +0x20f11185, 0x20f8aaa9, 0x2100443e, 0x2107de43, 0x210f78b7, 0x2117139c, 0x211eaef0, 0x21264ab5, +0x212de6e9, 0x2135838d, 0x213d20a0, 0x2144be24, 0x214c5c16, 0x2153fa79, 0x215b994b, 0x2163388c, +0x216ad83d, 0x2172785d, 0x217a18ec, 0x2181b9ea, 0x21895b58, 0x2190fd35, 0x21989f81, 0x21a0423c, +0x21a7e566, 0x21af88ff, 0x21b72d06, 0x21bed17d, 0x21c67663, 0x21ce1bb7, 0x21d5c17a, 0x21dd67ab, +0x21e50e4b, 0x21ecb55a, 0x21f45cd7, 0x21fc04c3, 0x2203ad1d, 0x220b55e5, 0x2212ff1c, 0x221aa8c1, +0x222252d4, 0x2229fd56, 0x2231a845, 0x223953a3, 0x2240ff6e, 0x2248aba8, 0x2250584f, 0x22580565, +0x225fb2e8, 0x226760d9, 0x226f0f37, 0x2276be04, 0x227e6d3e, 0x22861ce5, 0x228dccfa, 0x22957d7d, +0x229d2e6d, 0x22a4dfcb, 0x22ac9195, 0x22b443cd, 0x22bbf673, 0x22c3a985, 0x22cb5d05, 0x22d310f2, +0x22dac54c, 0x22e27a13, 0x22ea2f47, 0x22f1e4e8, 0x22f99af5, 0x23015170, 0x23090857, 0x2310bfab, +0x2318776c, 0x23202f99, 0x2327e833, 0x232fa13a, 0x23375aad, 0x233f148c, 0x2346ced8, 0x234e8991, +0x235644b5, 0x235e0046, 0x2365bc43, 0x236d78ac, 0x23753582, 0x237cf2c3, 0x2384b071, 0x238c6e8a, +0x23942d10, 0x239bec01, 0x23a3ab5e, 0x23ab6b28, 0x23b32b5c, 0x23baebfd, 0x23c2ad09, 0x23ca6e81, +0x23d23064, 0x23d9f2b3, 0x23e1b56e, 0x23e97894, 0x23f13c25, 0x23f90022, 0x2400c48a, 0x2408895d, +0x24104e9b, 0x24181445, 0x241fda5a, 0x2427a0da, 0x242f67c5, 0x24372f1a, 0x243ef6db, 0x2446bf07, +0x244e879e, 0x2456509f, 0x245e1a0b, 0x2465e3e2, 0x246dae24, 0x247578d0, 0x247d43e7, 0x24850f68, +0x248cdb54, 0x2494a7ab, 0x249c746b, 0x24a44197, 0x24ac0f2c, 0x24b3dd2c, 0x24bbab96, 0x24c37a6a, +0x24cb49a8, 0x24d31951, 0x24dae963, 0x24e2b9e0, 0x24ea8ac6, 0x24f25c17, 0x24fa2dd1, 0x2501fff5, +0x2509d283, 0x2511a57b, 0x251978dc, 0x25214ca7, 0x252920dc, 0x2530f57b, 0x2538ca82, 0x25409ff4, +0x254875cf, 0x25504c13, 0x255822c0, 0x255ff9d7, 0x2567d157, 0x256fa941, 0x25778193, 0x257f5a4f, +0x25873374, 0x258f0d02, 0x2596e6f9, 0x259ec159, 0x25a69c22, 0x25ae7753, 0x25b652ee, 0x25be2ef1, +0x25c60b5e, 0x25cde833, 0x25d5c570, 0x25dda316, 0x25e58125, 0x25ed5f9d, 0x25f53e7c, 0x25fd1dc5, +0x2604fd76, 0x260cdd8f, 0x2614be10, 0x261c9efa, 0x2624804c, 0x262c6206, 0x26344429, 0x263c26b3, +0x264409a6, 0x264bed01, 0x2653d0c3, 0x265bb4ee, 0x26639980, 0x266b7e7b, 0x267363dd, 0x267b49a7, +0x26832fd9, 0x268b1673, 0x2692fd74, 0x269ae4dd, 0x26a2ccad, 0x26aab4e5, 0x26b29d85, 0x26ba868c, +0x26c26ffa, 0x26ca59d0, 0x26d2440d, 0x26da2eb1, 0x26e219bd, 0x26ea0530, 0x26f1f10a, 0x26f9dd4b, +0x2701c9f4, 0x2709b703, 0x2711a479, 0x27199257, 0x2721809b, 0x27296f46, 0x27315e58, 0x27394dd1, +0x27413db0, 0x27492df7, 0x27511ea4, 0x27590fb7, 0x27610132, 0x2768f312, 0x2770e55a, 0x2778d808, +0x2780cb1c, 0x2788be96, 0x2790b277, 0x2798a6bf, 0x27a09b6c, 0x27a89080, 0x27b085fa, 0x27b87bdb, +0x27c07221, 0x27c868cd, 0x27d05fe0, 0x27d85758, 0x27e04f37, 0x27e8477b, 0x27f04026, 0x27f83936, +0x280032ac, 0x28082c87, 0x281026c9, 0x28182170, 0x28201c7d, 0x282817ef, 0x283013c7, 0x28381004, +0x28400ca7, 0x284809b0, 0x2850071d, 0x285804f1, 0x28600329, 0x286801c7, 0x287000ca, 0x28780032, +0x287fffff, 0x28880032, 0x289000ca, 0x289801c6, 0x28a00328, 0x28a804ef, 0x28b0071b, 0x28b809ab, +0x28c00ca1, 0x28c80ffb, 0x28d013ba, 0x28d817de, 0x28e01c66, 0x28e82153, 0x28f026a5, 0x28f82c5b, +0x29003276, 0x290838f6, 0x29103fda, 0x29184722, 0x29204ecf, 0x292856e0, 0x29305f55, 0x2938682f, +0x2940716d, 0x29487b0f, 0x29508516, 0x29588f80, 0x29609a4f, 0x2968a582, 0x2970b118, 0x2978bd13, +0x2980c972, 0x2988d634, 0x2990e35a, 0x2998f0e5, 0x29a0fed3, 0x29a90d24, 0x29b11bda, 0x29b92af3, +0x29c13a70, 0x29c94a50, 0x29d15a94, 0x29d96b3c, 0x29e17c47, 0x29e98db5, 0x29f19f87, 0x29f9b1bc, +0x2a01c455, 0x2a09d751, 0x2a11eab0, 0x2a19fe72, 0x2a221298, 0x2a2a2721, 0x2a323c0d, 0x2a3a515c, +0x2a42670e, 0x2a4a7d23, 0x2a52939b, 0x2a5aaa75, 0x2a62c1b3, 0x2a6ad954, 0x2a72f157, 0x2a7b09be, +0x2a832287, 0x2a8b3bb2, 0x2a935541, 0x2a9b6f32, 0x2aa38986, 0x2aaba43c, 0x2ab3bf55, 0x2abbdad0, +0x2ac3f6ad, 0x2acc12ee, 0x2ad42f90, 0x2adc4c95, 0x2ae469fc, 0x2aec87c6, 0x2af4a5f1, 0x2afcc47f, +0x2b04e36f, 0x2b0d02c1, 0x2b152276, 0x2b1d428c, 0x2b256304, 0x2b2d83df, 0x2b35a51b, 0x2b3dc6b9, +0x2b45e8b9, 0x2b4e0b1b, 0x2b562ddf, 0x2b5e5104, 0x2b66748c, 0x2b6e9875, 0x2b76bcbf, 0x2b7ee16b, +0x2b870679, 0x2b8f2be9, 0x2b9751b9, 0x2b9f77ec, 0x2ba79e80, 0x2bafc575, 0x2bb7eccb, 0x2bc01483, +0x2bc83c9d, 0x2bd06517, 0x2bd88df3, 0x2be0b730, 0x2be8e0ce, 0x2bf10acd, 0x2bf9352e, 0x2c015fef, +0x2c098b11, 0x2c11b695, 0x2c19e279, 0x2c220ebf, 0x2c2a3b65, 0x2c32686c, 0x2c3a95d4, 0x2c42c39c, +0x2c4af1c6, 0x2c532050, 0x2c5b4f3a, 0x2c637e86, 0x2c6bae32, 0x2c73de3e, 0x2c7c0eab, 0x2c843f79, +0x2c8c70a7, 0x2c94a236, 0x2c9cd424, 0x2ca50674, 0x2cad3923, 0x2cb56c33, 0x2cbd9fa3, 0x2cc5d374, +0x2cce07a4, 0x2cd63c35, 0x2cde7126, 0x2ce6a677, 0x2ceedc28, 0x2cf71238, 0x2cff48a9, 0x2d077f7a, +0x2d0fb6ab, 0x2d17ee3c, 0x2d20262c, 0x2d285e7d, 0x2d30972d, 0x2d38d03d, 0x2d4109ac, 0x2d49437c, +0x2d517daa, 0x2d59b839, 0x2d61f327, 0x2d6a2e75, 0x2d726a22, 0x2d7aa62e, 0x2d82e29b, 0x2d8b1f66, +0x2d935c91, 0x2d9b9a1b, 0x2da3d804, 0x2dac164d, 0x2db454f5, 0x2dbc93fc, 0x2dc4d363, 0x2dcd1328, +0x2dd5534d, 0x2ddd93d0, 0x2de5d4b3, 0x2dee15f5, 0x2df65795, 0x2dfe9995, 0x2e06dbf4, 0x2e0f1eb1, +0x2e1761cd, 0x2e1fa548, 0x2e27e922, 0x2e302d5a, 0x2e3871f2, 0x2e40b6e8, 0x2e48fc3c, 0x2e5141ef, +0x2e598801, 0x2e61ce71, 0x2e6a1540, 0x2e725c6d, 0x2e7aa3f9, 0x2e82ebe3, 0x2e8b342b, 0x2e937cd2, +0x2e9bc5d7, 0x2ea40f3b, 0x2eac58fc, 0x2eb4a31c, 0x2ebced9a, 0x2ec53876, 0x2ecd83b0, 0x2ed5cf49, +0x2ede1b3f, 0x2ee66794, 0x2eeeb446, 0x2ef70156, 0x2eff4ec5, 0x2f079c91, 0x2f0feabb, 0x2f183942, +0x2f208828, 0x2f28d76b, 0x2f31270c, 0x2f39770b, 0x2f41c768, 0x2f4a1822, 0x2f526939, 0x2f5abaaf, +0x2f630c81, 0x2f6b5eb2, 0x2f73b13f, 0x2f7c042a, 0x2f845773, 0x2f8cab19, 0x2f94ff1c, 0x2f9d537d, +0x2fa5a83a, 0x2fadfd56, 0x2fb652ce, 0x2fbea8a3, 0x2fc6fed6, 0x2fcf5566, 0x2fd7ac52, 0x2fe0039c, +0x2fe85b43, 0x2ff0b347, 0x2ff90ba8, 0x30016466, 0x3009bd80, 0x301216f8, 0x301a70cc, 0x3022cafd, +0x302b258b, 0x30338076, 0x303bdbbd, 0x30443761, 0x304c9362, 0x3054efbf, 0x305d4c79, 0x3065a98f, +0x306e0702, 0x307664d2, 0x307ec2fe, 0x30872186, 0x308f806b, 0x3097dfac, 0x30a03f49, 0x30a89f43, +0x30b0ff99, 0x30b9604b, 0x30c1c159, 0x30ca22c4, 0x30d2848a, 0x30dae6ad, 0x30e3492c, 0x30ebac07, +0x30f40f3e, 0x30fc72d1, 0x3104d6c0, 0x310d3b0b, 0x31159fb1, 0x311e04b4, 0x31266a12, 0x312ecfcd, +0x313735e3, 0x313f9c55, 0x31480322, 0x31506a4b, 0x3158d1d0, 0x316139b0, 0x3169a1ed, 0x31720a84, +0x317a7377, 0x3182dcc6, 0x318b4670, 0x3193b076, 0x319c1ad6, 0x31a48593, 0x31acf0aa, 0x31b55c1d, +0x31bdc7ec, 0x31c63415, 0x31cea09a, 0x31d70d7a, 0x31df7ab5, 0x31e7e84b, 0x31f0563d, 0x31f8c489, +0x32013331, 0x3209a233, 0x32121191, 0x321a8149, 0x3222f15d, 0x322b61cb, 0x3233d294, 0x323c43b8, +0x3244b537, 0x324d2711, 0x32559945, 0x325e0bd4, 0x32667ebe, 0x326ef202, 0x327765a1, 0x327fd99b, +0x32884def, 0x3290c29e, 0x329937a7, 0x32a1ad0b, 0x32aa22c9, 0x32b298e2, 0x32bb0f55, 0x32c38622, +0x32cbfd4a, 0x32d474cc, 0x32dceca8, 0x32e564df, 0x32eddd70, 0x32f6565b, 0x32fecfa0, 0x3307493f, +0x330fc338, 0x33183d8c, 0x3320b839, 0x33293341, 0x3331aea2, 0x333a2a5e, 0x3342a673, 0x334b22e2, +0x33539fab, 0x335c1cce, 0x33649a4b, 0x336d1821, 0x33759652, 0x337e14dc, 0x338693bf, 0x338f12fd, +0x33979294, 0x33a01284, 0x33a892cf, 0x33b11372, 0x33b9946f, 0x33c215c6, 0x33ca9776, 0x33d31980, +0x33db9be3, 0x33e41ea0, 0x33eca1b5, 0x33f52524, 0x33fda8ed, 0x34062d0e, 0x340eb189, 0x3417365d, +0x341fbb8b, 0x34284111, 0x3430c6f1, 0x34394d29, 0x3441d3bb, 0x344a5aa6, 0x3452e1e9, 0x345b6986, +0x3463f17c, 0x346c79ca, 0x34750272, 0x347d8b72, 0x348614cb, 0x348e9e7d, 0x34972888, 0x349fb2eb, +0x34a83da8, 0x34b0c8bd, 0x34b9542a, 0x34c1dff0, 0x34ca6c0f, 0x34d2f887, 0x34db8557, 0x34e4127f, +0x34eca000, 0x34f52dda, 0x34fdbc0c, 0x35064a96, 0x350ed979, 0x351768b4, 0x351ff847, 0x35288833, +0x35311877, 0x3539a913, 0x35423a08, 0x354acb54, 0x35535cf9, 0x355beef6, 0x3564814b, 0x356d13f8, +0x3575a6fe, 0x357e3a5b, 0x3586ce10, 0x358f621d, 0x3597f682, 0x35a08b40, 0x35a92055, 0x35b1b5c1, +0x35ba4b86, 0x35c2e1a3, 0x35cb7817, 0x35d40ee3, 0x35dca607, 0x35e53d82, 0x35edd555, 0x35f66d80, +0x35ff0602, 0x36079edc, 0x3610380e, 0x3618d197, 0x36216b77, 0x362a05af, 0x3632a03f, 0x363b3b26, +0x3643d664, 0x364c71fa, 0x36550de7, 0x365daa2b, 0x366646c7, 0x366ee3ba, 0x36778104, 0x36801ea5, +0x3688bc9e, 0x36915aee, 0x3699f994, 0x36a29892, 0x36ab37e7, 0x36b3d793, 0x36bc7796, 0x36c517f1, +0x36cdb8a2, 0x36d659aa, 0x36defb08, 0x36e79cbe, 0x36f03ecb, 0x36f8e12e, 0x370183e9, 0x370a26fa, +0x3712ca62, 0x371b6e20, 0x37241235, 0x372cb6a1, 0x37355b64, 0x373e007d, 0x3746a5ed, 0x374f4bb3, +0x3757f1d0, 0x37609844, 0x37693f0e, 0x3771e62e, 0x377a8da5, 0x37833572, 0x378bdd96, 0x37948610, +0x379d2ee0, 0x37a5d807, 0x37ae8183, 0x37b72b57, 0x37bfd580, 0x37c87fff, 0x37d12ad5, 0x37d9d601, +0x37e28183, 0x37eb2d5b, 0x37f3d989, 0x37fc860e, 0x380532e8, 0x380de018, 0x38168d9e, 0x381f3b7b, +0x3827e9ad, 0x38309835, 0x38394712, 0x3841f646, 0x384aa5d0, 0x385355af, 0x385c05e4, 0x3864b66f, +0x386d674f, 0x38761885, 0x387eca11, 0x38877bf2, 0x38902e29, 0x3898e0b6, 0x38a19398, 0x38aa46d0, +0x38b2fa5d, 0x38bbae40, 0x38c46278, 0x38cd1705, 0x38d5cbe8, 0x38de8120, 0x38e736ae, 0x38efec91, +0x38f8a2c9, 0x39015957, 0x390a103a, 0x3912c772, 0x391b7eff, 0x392436e1, 0x392cef19, 0x3935a7a5, +0x393e6087, 0x394719be, 0x394fd34a, 0x39588d2b, 0x39614760, 0x396a01eb, 0x3972bccb, 0x397b7800, +0x39843389, 0x398cef68, 0x3995ab9b, 0x399e6823, 0x39a72500, 0x39afe232, 0x39b89fb8, 0x39c15d93, +0x39ca1bc3, 0x39d2da47, 0x39db9921, 0x39e4584e, 0x39ed17d1, 0x39f5d7a8, 0x39fe97d3, 0x3a075853, +0x3a101927, 0x3a18da50, 0x3a219bce, 0x3a2a5d9f, 0x3a331fc5, 0x3a3be240, 0x3a44a50f, 0x3a4d6832, +0x3a562ba9, 0x3a5eef75, 0x3a67b395, 0x3a707809, 0x3a793cd2, 0x3a8201ee, 0x3a8ac75f, 0x3a938d24, +0x3a9c533d, 0x3aa519aa, 0x3aade06b, 0x3ab6a780, 0x3abf6ee9, 0x3ac836a6, 0x3ad0feb7, 0x3ad9c71c, +0x3ae28fd5, 0x3aeb58e1, 0x3af42242, 0x3afcebf6, 0x3b05b5fe, 0x3b0e805a, 0x3b174b0a, 0x3b20160d, +0x3b28e164, 0x3b31ad0f, 0x3b3a790e, 0x3b434560, 0x3b4c1205, 0x3b54deff, 0x3b5dac4b, 0x3b6679ec, +0x3b6f47e0, 0x3b781627, 0x3b80e4c2, 0x3b89b3b0, 0x3b9282f2, 0x3b9b5287, 0x3ba4226f, 0x3bacf2ab, +0x3bb5c33a, 0x3bbe941c, 0x3bc76552, 0x3bd036db, 0x3bd908b7, 0x3be1dae6, 0x3beaad69, 0x3bf3803e, +0x3bfc5367, 0x3c0526e3, 0x3c0dfab2, 0x3c16ced4, 0x3c1fa349, 0x3c287811, 0x3c314d2c, 0x3c3a229a, +0x3c42f85b, 0x3c4bce6f, 0x3c54a4d5, 0x3c5d7b8f, 0x3c66529b, 0x3c6f29fa, 0x3c7801ac, 0x3c80d9b1, +0x3c89b209, 0x3c928ab3, 0x3c9b63b0, 0x3ca43cff, 0x3cad16a2, 0x3cb5f097, 0x3cbecade, 0x3cc7a578, +0x3cd08065, 0x3cd95ba4, 0x3ce23736, 0x3ceb131a, 0x3cf3ef50, 0x3cfccbd9, 0x3d05a8b5, 0x3d0e85e3, +0x3d176363, 0x3d204136, 0x3d291f5b, 0x3d31fdd2, 0x3d3adc9b, 0x3d43bbb7, 0x3d4c9b25, 0x3d557ae5, +0x3d5e5af7, 0x3d673b5c, 0x3d701c13, 0x3d78fd1b, 0x3d81de76, 0x3d8ac023, 0x3d93a222, 0x3d9c8473, +0x3da56716, 0x3dae4a0b, 0x3db72d52, 0x3dc010eb, 0x3dc8f4d6, 0x3dd1d912, 0x3ddabda1, 0x3de3a281, +0x3dec87b3, 0x3df56d37, 0x3dfe530d, 0x3e073934, 0x3e101fad, 0x3e190678, 0x3e21ed95, 0x3e2ad503, +0x3e33bcc3, 0x3e3ca4d4, 0x3e458d37, 0x3e4e75ec, 0x3e575ef2, 0x3e60484a, 0x3e6931f3, 0x3e721bed, +0x3e7b0639, 0x3e83f0d7, 0x3e8cdbc6, 0x3e95c706, 0x3e9eb298, 0x3ea79e7a, 0x3eb08aaf, 0x3eb97734, +0x3ec2640b, 0x3ecb5133, 0x3ed43eac, 0x3edd2c77, 0x3ee61a93, 0x3eef08ff, 0x3ef7f7bd, 0x3f00e6cc, +0x3f09d62c, 0x3f12c5de, 0x3f1bb5e0, 0x3f24a633, 0x3f2d96d7, 0x3f3687cd, 0x3f3f7913, 0x3f486aaa, +0x3f515c92, 0x3f5a4ecb, 0x3f634155, 0x3f6c342f, 0x3f75275b, 0x3f7e1ad7, 0x3f870ea4, 0x3f9002c2, +0x3f98f730, 0x3fa1ebef, 0x3faae0ff, 0x3fb3d660, 0x3fbccc11, 0x3fc5c213, 0x3fceb865, 0x3fd7af08, +0x3fe0a5fc, 0x3fe99d40, 0x3ff294d4, 0x3ffb8cb9, 0x400484ef, 0x400d7d75, 0x4016764b, 0x401f6f72, +0x402868e9, 0x403162b1, 0x403a5cc8, 0x40435730, 0x404c51e9, 0x40554cf2, 0x405e484b, 0x406743f4, +0x40703fed, 0x40793c37, 0x408238d0, 0x408b35ba, 0x409432f4, 0x409d307e, 0x40a62e58, 0x40af2c82, +0x40b82afd, 0x40c129c7, 0x40ca28e1, 0x40d3284b, 0x40dc2805, 0x40e5280f, 0x40ee2869, 0x40f72913, +0x41002a0c, 0x41092b56, 0x41122cef, 0x411b2ed8, 0x41243111, 0x412d3399, 0x41363672, 0x413f399a, +0x41483d11, 0x415140d9, 0x415a44f0, 0x41634956, 0x416c4e0c, 0x41755312, 0x417e5867, 0x41875e0c, +0x41906401, 0x41996a44, 0x41a270d8, 0x41ab77ba, 0x41b47eed, 0x41bd866e, 0x41c68e3f, 0x41cf965f, +0x41d89ecf, 0x41e1a78e, 0x41eab09c, 0x41f3b9fa, 0x41fcc3a6, 0x4205cda2, 0x420ed7ee, 0x4217e288, +0x4220ed72, 0x4229f8aa, 0x42330432, 0x423c1009, 0x42451c2f, 0x424e28a4, 0x42573569, 0x4260427c, +0x42694fde, 0x42725d8f, 0x427b6b8f, 0x428479de, 0x428d887c, 0x42969769, 0x429fa6a5, 0x42a8b62f, +0x42b1c609, 0x42bad631, 0x42c3e6a8, 0x42ccf76e, 0x42d60882, 0x42df19e5, 0x42e82b97, 0x42f13d98, +0x42fa4fe7, 0x43036285, 0x430c7572, 0x431588ad, 0x431e9c37, 0x4327b00f, 0x4330c436, 0x4339d8ab, +0x4342ed6f, 0x434c0282, 0x435517e3, 0x435e2d92, 0x4367438f, 0x437059dc, 0x43797076, 0x4382875f, +0x438b9e96, 0x4394b61b, 0x439dcdef, 0x43a6e611, 0x43affe81, 0x43b91740, 0x43c2304d, 0x43cb49a8, +0x43d46351, 0x43dd7d48, 0x43e6978d, 0x43efb221, 0x43f8cd02, 0x4401e832, 0x440b03af, 0x44141f7b, +0x441d3b95, 0x442657fc, 0x442f74b2, 0x443891b6, 0x4441af07, 0x444acca7, 0x4453ea94, 0x445d08cf, +0x44662758, 0x446f462f, 0x44786553, 0x448184c6, 0x448aa486, 0x4493c494, 0x449ce4f0, 0x44a60599, +0x44af2690, 0x44b847d5, 0x44c16967, 0x44ca8b47, 0x44d3ad74, 0x44dccfef, 0x44e5f2b8, 0x44ef15ce, +0x44f83932, 0x45015ce3, 0x450a80e2, 0x4513a52e, 0x451cc9c8, 0x4525eeaf, 0x452f13e3, 0x45383965, +0x45415f34, 0x454a8551, 0x4553abbb, 0x455cd272, 0x4565f976, 0x456f20c8, 0x45784867, 0x45817053, +0x458a988c, 0x4593c113, 0x459ce9e7, 0x45a61307, 0x45af3c75, 0x45b86630, 0x45c19039, 0x45caba8e, +0x45d3e530, 0x45dd101f, 0x45e63b5c, 0x45ef66e5, 0x45f892bb, 0x4601bede, 0x460aeb4e, 0x4614180b, +0x461d4515, 0x4626726c, 0x462fa00f, 0x4638ce00, 0x4641fc3d, 0x464b2ac7, 0x4654599e, 0x465d88c1, +0x4666b832, 0x466fe7ef, 0x467917f8, 0x4682484e, 0x468b78f1, 0x4694a9e1, 0x469ddb1d, 0x46a70ca6, +0x46b03e7b, 0x46b9709d, 0x46c2a30c, 0x46cbd5c7, 0x46d508ce, 0x46de3c22, 0x46e76fc2, 0x46f0a3af, +0x46f9d7e9, 0x47030c6e, 0x470c4140, 0x4715765f, 0x471eabc9, 0x4727e180, 0x47311784, 0x473a4dd3, +0x4743846f, 0x474cbb57, 0x4755f28c, 0x475f2a0c, 0x476861d9, 0x477199f2, 0x477ad257, 0x47840b08, +0x478d4405, 0x47967d4f, 0x479fb6e4, 0x47a8f0c5, 0x47b22af3, 0x47bb656c, 0x47c4a032, 0x47cddb43, +0x47d716a1, 0x47e0524a, 0x47e98e40, 0x47f2ca81, 0x47fc070e, 0x480543e7, 0x480e810c, 0x4817be7c, +0x4820fc39, 0x482a3a41, 0x48337895, 0x483cb735, 0x4845f620, 0x484f3557, 0x485874da, 0x4861b4a8, +0x486af4c3, 0x48743528, 0x487d75da, 0x4886b6d7, 0x488ff81f, 0x489939b3, 0x48a27b93, 0x48abbdbe, +0x48b50035, 0x48be42f7, 0x48c78605, 0x48d0c95e, 0x48da0d02, 0x48e350f2, 0x48ec952e, 0x48f5d9b4, +0x48ff1e86, 0x490863a4, 0x4911a90c, 0x491aeec0, 0x492434bf, 0x492d7b0a, 0x4936c1a0, 0x49400881, +0x49494fad, 0x49529724, 0x495bdee7, 0x496526f4, 0x496e6f4d, 0x4977b7f1, 0x498100e0, 0x498a4a1a, +0x4993939f, 0x499cdd6f, 0x49a6278a, 0x49af71f0, 0x49b8bca2, 0x49c2079e, 0x49cb52e5, 0x49d49e77, +0x49ddea53, 0x49e7367b, 0x49f082ee, 0x49f9cfab, 0x4a031cb4, 0x4a0c6a07, 0x4a15b7a5, 0x4a1f058d, +0x4a2853c1, 0x4a31a23f, 0x4a3af108, 0x4a44401b, 0x4a4d8f7a, 0x4a56df23, 0x4a602f16, 0x4a697f55, +0x4a72cfdd, 0x4a7c20b1, 0x4a8571cf, 0x4a8ec337, 0x4a9814eb, 0x4aa166e8, 0x4aaab930, 0x4ab40bc3, +0x4abd5ea0, 0x4ac6b1c8, 0x4ad0053a, 0x4ad958f6, 0x4ae2acfd, 0x4aec014e, 0x4af555e9, 0x4afeaacf, +0x4b07ffff, 0x4b11557a, 0x4b1aab3f, 0x4b24014e, 0x4b2d57a7, 0x4b36ae4b, 0x4b400538, 0x4b495c70, +0x4b52b3f2, 0x4b5c0bbf, 0x4b6563d5, 0x4b6ebc36, 0x4b7814e0, 0x4b816dd5, 0x4b8ac714, 0x4b94209d, +0x4b9d7a6f, 0x4ba6d48c, 0x4bb02ef3, 0x4bb989a4, 0x4bc2e49f, 0x4bcc3fe4, 0x4bd59b72, 0x4bdef74b, +0x4be8536e, 0x4bf1afda, 0x4bfb0c90, 0x4c046990, 0x4c0dc6da, 0x4c17246e, 0x4c20824b, 0x4c29e073, +0x4c333ee4, 0x4c3c9d9e, 0x4c45fca3, 0x4c4f5bf1, 0x4c58bb89, 0x4c621b6a, 0x4c6b7b95, 0x4c74dc0a, +0x4c7e3cc9, 0x4c879dd0, 0x4c90ff22, 0x4c9a60bd, 0x4ca3c2a2, 0x4cad24d0, 0x4cb68747, 0x4cbfea09, +0x4cc94d13, 0x4cd2b067, 0x4cdc1405, 0x4ce577ec, 0x4ceedc1c, 0x4cf84096, 0x4d01a559, 0x4d0b0a65, +0x4d146fbb, 0x4d1dd55a, 0x4d273b42, 0x4d30a174, 0x4d3a07ee, 0x4d436eb2, 0x4d4cd5c0, 0x4d563d16, +0x4d5fa4b6, 0x4d690c9f, 0x4d7274d1, 0x4d7bdd4c, 0x4d854610, 0x4d8eaf1e, 0x4d981874, 0x4da18214, +0x4daaebfc, 0x4db4562e, 0x4dbdc0a8, 0x4dc72b6c, 0x4dd09679, 0x4dda01ce, 0x4de36d6d, 0x4decd954, +0x4df64584, 0x4dffb1fe, 0x4e091ec0, 0x4e128bcb, 0x4e1bf91f, 0x4e2566bb, 0x4e2ed4a1, 0x4e3842cf, +0x4e41b146, 0x4e4b2006, 0x4e548f0e, 0x4e5dfe5f, 0x4e676df9, 0x4e70dddc, 0x4e7a4e07, 0x4e83be7b, +0x4e8d2f38, 0x4e96a03d, 0x4ea0118b, 0x4ea98321, 0x4eb2f500, 0x4ebc6728, 0x4ec5d998, 0x4ecf4c50, +0x4ed8bf51, 0x4ee2329b, 0x4eeba62d, 0x4ef51a07, 0x4efe8e2a, 0x4f080296, 0x4f117749, 0x4f1aec45, +0x4f24618a, 0x4f2dd717, 0x4f374cec, 0x4f40c309, 0x4f4a396f, 0x4f53b01d, 0x4f5d2713, 0x4f669e52, +0x4f7015d9, 0x4f798da8, 0x4f8305bf, 0x4f8c7e1e, 0x4f95f6c6, 0x4f9f6fb5, 0x4fa8e8ed, 0x4fb2626d, +0x4fbbdc35, 0x4fc55645, 0x4fced09d, 0x4fd84b3e, 0x4fe1c626, 0x4feb4156, 0x4ff4bcce, 0x4ffe388f, +0x5007b497, 0x501130e7, 0x501aad7f, 0x50242a5f, 0x502da787, 0x503724f7, 0x5040a2ae, 0x504a20ae, +0x50539ef5, 0x505d1d84, 0x50669c5b, 0x50701b7a, 0x50799ae0, 0x50831a8e, 0x508c9a84, 0x50961ac2, +0x509f9b47, 0x50a91c14, 0x50b29d29, 0x50bc1e85, 0x50c5a029, 0x50cf2215, 0x50d8a448, 0x50e226c2, +0x50eba985, 0x50f52c8f, 0x50feafe0, 0x51083379, 0x5111b759, 0x511b3b81, 0x5124bff1, 0x512e44a7, +0x5137c9a6, 0x51414eeb, 0x514ad478, 0x51545a4d, 0x515de069, 0x516766cc, 0x5170ed76, 0x517a7468, +0x5183fba1, 0x518d8322, 0x51970ae9, 0x51a092f8, 0x51aa1b4e, 0x51b3a3ec, 0x51bd2cd0, 0x51c6b5fc, +0x51d03f6f, 0x51d9c929, 0x51e3532b, 0x51ecdd73, 0x51f66802, 0x51fff2d9, 0x52097df7, 0x5213095b, +0x521c9507, 0x522620fa, 0x522fad34, 0x523939b5, 0x5242c67c, 0x524c538b, 0x5255e0e1, 0x525f6e7e, +0x5268fc61, 0x52728a8c, 0x527c18fd, 0x5285a7b5, 0x528f36b4, 0x5298c5fa, 0x52a25587, 0x52abe55a, +0x52b57575, 0x52bf05d6, 0x52c8967d, 0x52d2276c, 0x52dbb8a1, 0x52e54a1d, 0x52eedbe0, 0x52f86de9, +0x53020039, 0x530b92d0, 0x531525ad, 0x531eb8d1, 0x53284c3c, 0x5331dfed, 0x533b73e4, 0x53450823, +0x534e9ca7, 0x53583173, 0x5361c684, 0x536b5bdc, 0x5374f17b, 0x537e8760, 0x53881d8c, 0x5391b3fe, +0x539b4ab6, 0x53a4e1b5, 0x53ae78fa, 0x53b81086, 0x53c1a858, 0x53cb4070, 0x53d4d8ce, 0x53de7173, +0x53e80a5e, 0x53f1a390, 0x53fb3d07, 0x5404d6c5, 0x540e70c9, 0x54180b13, 0x5421a5a4, 0x542b407a, +0x5434db97, 0x543e76fa, 0x544812a3, 0x5451ae92, 0x545b4ac8, 0x5464e743, 0x546e8404, 0x5478210c, +0x5481be59, 0x548b5bed, 0x5494f9c6, 0x549e97e5, 0x54a8364b, 0x54b1d4f6, 0x54bb73e8, 0x54c5131f, +0x54ceb29c, 0x54d8525f, 0x54e1f268, 0x54eb92b6, 0x54f5334b, 0x54fed425, 0x55087546, 0x551216ac, +0x551bb858, 0x55255a49, 0x552efc80, 0x55389efe, 0x554241c0, 0x554be4c9, 0x55558817, 0x555f2bab, +0x5568cf84, 0x557273a3, 0x557c1808, 0x5585bcb3, 0x558f61a3, 0x559906d8, 0x55a2ac53, 0x55ac5214, +0x55b5f81a, 0x55bf9e66, 0x55c944f7, 0x55d2ebce, 0x55dc92ea, 0x55e63a4c, 0x55efe1f3, 0x55f989e0, +0x56033212, 0x560cda89, 0x56168346, 0x56202c48, 0x5629d58f, 0x56337f1c, 0x563d28ee, 0x5646d306, +0x56507d62, 0x565a2804, 0x5663d2ec, 0x566d7e18, 0x5677298a, 0x5680d541, 0x568a813d, 0x56942d7e, +0x569dda05, 0x56a786d1, 0x56b133e1, 0x56bae137, 0x56c48ed2, 0x56ce3cb3, 0x56d7ead8, 0x56e19942, +0x56eb47f1, 0x56f4f6e6, 0x56fea61f, 0x5708559e, 0x57120561, 0x571bb569, 0x572565b7, 0x572f1649, +0x5738c720, 0x5742783c, 0x574c299e, 0x5755db43, 0x575f8d2e, 0x57693f5e, 0x5772f1d2, 0x577ca48c, +0x5786578a, 0x57900acd, 0x5799be54, 0x57a37221, 0x57ad2632, 0x57b6da88, 0x57c08f23, 0x57ca4402, +0x57d3f926, 0x57ddae8f, 0x57e7643c, 0x57f11a2f, 0x57fad065, 0x580486e1, 0x580e3da1, 0x5817f4a5, +0x5821abee, 0x582b637c, 0x58351b4e, 0x583ed365, 0x58488bc0, 0x58524460, 0x585bfd44, 0x5865b66d, +0x586f6fda, 0x5879298b, 0x5882e381, 0x588c9dbc, 0x5896583b, 0x58a012fe, 0x58a9ce05, 0x58b38951, +0x58bd44e2, 0x58c700b6, 0x58d0bccf, 0x58da792c, 0x58e435ce, 0x58edf2b4, 0x58f7afde, 0x59016d4c, +0x590b2afe, 0x5914e8f5, 0x591ea730, 0x592865af, 0x59322472, 0x593be379, 0x5945a2c5, 0x594f6255, +0x59592228, 0x5962e240, 0x596ca29c, 0x5976633c, 0x59802420, 0x5989e548, 0x5993a6b4, 0x599d6864, +0x59a72a58, 0x59b0ec90, 0x59baaf0c, 0x59c471cc, 0x59ce34d0, 0x59d7f818, 0x59e1bba3, 0x59eb7f73, +0x59f54386, 0x59ff07dd, 0x5a08cc79, 0x5a129158, 0x5a1c567a, 0x5a261be1, 0x5a2fe18b, 0x5a39a779, +0x5a436dab, 0x5a4d3421, 0x5a56fada, 0x5a60c1d8, 0x5a6a8918, 0x5a74509d, 0x5a7e1865, 0x5a87e071, +0x5a91a8c0, 0x5a9b7153, 0x5aa53a2a, 0x5aaf0344, 0x5ab8cca2, 0x5ac29644, 0x5acc6029, 0x5ad62a51, +0x5adff4bd, 0x5ae9bf6d, 0x5af38a60, 0x5afd5597, 0x5b072111, 0x5b10ecce, 0x5b1ab8cf, 0x5b248514, +0x5b2e519c, 0x5b381e67, 0x5b41eb76, 0x5b4bb8c8, 0x5b55865d, 0x5b5f5436, 0x5b692252, 0x5b72f0b1, +0x5b7cbf54, 0x5b868e3a, 0x5b905d63, 0x5b9a2cd0, 0x5ba3fc7f, 0x5badcc72, 0x5bb79ca9, 0x5bc16d22, +0x5bcb3ddf, 0x5bd50ede, 0x5bdee021, 0x5be8b1a7, 0x5bf28371, 0x5bfc557d, 0x5c0627cc, 0x5c0ffa5f, +0x5c19cd35, 0x5c23a04d, 0x5c2d73a9, 0x5c374748, 0x5c411b2a, 0x5c4aef4e, 0x5c54c3b6, 0x5c5e9861, +0x5c686d4f, 0x5c724280, 0x5c7c17f3, 0x5c85edaa, 0x5c8fc3a3, 0x5c9999e0, 0x5ca3705f, 0x5cad4721, +0x5cb71e26, 0x5cc0f56e, 0x5ccaccf9, 0x5cd4a4c6, 0x5cde7cd7, 0x5ce8552a, 0x5cf22dbf, 0x5cfc0698, +0x5d05dfb3, 0x5d0fb912, 0x5d1992b2, 0x5d236c96, 0x5d2d46bc, 0x5d372125, 0x5d40fbd1, 0x5d4ad6bf, +0x5d54b1f0, 0x5d5e8d63, 0x5d686919, 0x5d724512, 0x5d7c214d, 0x5d85fdcb, 0x5d8fda8b, 0x5d99b78e, +0x5da394d4, 0x5dad725c, 0x5db75026, 0x5dc12e33, 0x5dcb0c82, 0x5dd4eb14, 0x5ddec9e9, 0x5de8a8ff, +0x5df28858, 0x5dfc67f4, 0x5e0647d2, 0x5e1027f2, 0x5e1a0855, 0x5e23e8fa, 0x5e2dc9e1, 0x5e37ab0b, +0x5e418c77, 0x5e4b6e25, 0x5e555016, 0x5e5f3249, 0x5e6914be, 0x5e72f775, 0x5e7cda6f, 0x5e86bdab, +0x5e90a129, 0x5e9a84e9, 0x5ea468eb, 0x5eae4d30, 0x5eb831b6, 0x5ec2167f, 0x5ecbfb8a, 0x5ed5e0d7, +0x5edfc666, 0x5ee9ac37, 0x5ef3924a, 0x5efd78a0, 0x5f075f37, 0x5f114610, 0x5f1b2d2c, 0x5f251489, +0x5f2efc28, 0x5f38e40a, 0x5f42cc2d, 0x5f4cb492, 0x5f569d39, 0x5f608622, 0x5f6a6f4d, 0x5f7458ba, +0x5f7e4269, 0x5f882c5a, 0x5f92168c, 0x5f9c0100, 0x5fa5ebb6, 0x5fafd6ae, 0x5fb9c1e8, 0x5fc3ad64, +0x5fcd9921, 0x5fd78520, 0x5fe17161, 0x5feb5de3, 0x5ff54aa7, 0x5fff37ad, 0x600924f5, 0x6013127e, +0x601d0049, 0x6026ee56, 0x6030dca4, 0x603acb34, 0x6044ba05, 0x604ea918, 0x6058986d, 0x60628803, +0x606c77db, 0x607667f4, 0x6080584f, 0x608a48ec, 0x609439ca, 0x609e2ae9, 0x60a81c4a, 0x60b20dec, +0x60bbffd0, 0x60c5f1f5, 0x60cfe45c, 0x60d9d704, 0x60e3c9ed, 0x60edbd18, 0x60f7b084, 0x6101a432, +0x610b9821, 0x61158c51, 0x611f80c3, 0x61297576, 0x61336a6a, 0x613d5f9f, 0x61475516, 0x61514ace, +0x615b40c7, 0x61653702, 0x616f2d7e, 0x6179243a, 0x61831b38, 0x618d1278, 0x619709f8, 0x61a101ba, +0x61aaf9bd, 0x61b4f200, 0x61beea85, 0x61c8e34b, 0x61d2dc53, 0x61dcd59b, 0x61e6cf24, 0x61f0c8ee, +0x61fac2fa, 0x6204bd46, 0x620eb7d4, 0x6218b2a2, 0x6222adb1, 0x622ca902, 0x6236a493, 0x6240a065, +0x624a9c78, 0x625498cd, 0x625e9562, 0x62689238, 0x62728f4e, 0x627c8ca6, 0x62868a3e, 0x62908818, +0x629a8632, 0x62a4848d, 0x62ae8329, 0x62b88205, 0x62c28123, 0x62cc8081, 0x62d68020, 0x62e07fff, +0x62ea8020, 0x62f48081, 0x62fe8123, 0x63088205, 0x63128328, 0x631c848c, 0x63268631, 0x63308816, +0x633a8a3b, 0x63448ca2, 0x634e8f49, 0x63589230, 0x63629558, 0x636c98c1, 0x63769c6a, 0x6380a054, +0x638aa47e, 0x6394a8e9, 0x639ead94, 0x63a8b280, 0x63b2b7ac, 0x63bcbd19, 0x63c6c2c6, 0x63d0c8b3, +0x63dacee1, 0x63e4d550, 0x63eedbff, 0x63f8e2ee, 0x6402ea1d, 0x640cf18d, 0x6416f93e, 0x6421012e, +0x642b095f, 0x643511d0, 0x643f1a82, 0x64492374, 0x64532ca6, 0x645d3618, 0x64673fcb, 0x647149bd, +0x647b53f0, 0x64855e64, 0x648f6917, 0x6499740b, 0x64a37f3e, 0x64ad8ab2, 0x64b79666, 0x64c1a25b, +0x64cbae8f, 0x64d5bb03, 0x64dfc7b8, 0x64e9d4ad, 0x64f3e1e1, 0x64fdef56, 0x6507fd0b, 0x65120b00, +0x651c1934, 0x652627a9, 0x6530365e, 0x653a4553, 0x65445488, 0x654e63fd, 0x655873b1, 0x656283a6, +0x656c93db, 0x6576a44f, 0x6580b503, 0x658ac5f8, 0x6594d72c, 0x659ee8a0, 0x65a8fa54, 0x65b30c47, +0x65bd1e7b, 0x65c730ee, 0x65d143a1, 0x65db5694, 0x65e569c7, 0x65ef7d39, 0x65f990eb, 0x6603a4dd, +0x660db90f, 0x6617cd80, 0x6621e231, 0x662bf722, 0x66360c52, 0x664021c2, 0x664a3772, 0x66544d62, +0x665e6390, 0x666879ff, 0x667290ad, 0x667ca79b, 0x6686bec8, 0x6690d635, 0x669aede2, 0x66a505ce, +0x66af1df9, 0x66b93664, 0x66c34f0f, 0x66cd67f9, 0x66d78123, 0x66e19a8c, 0x66ebb434, 0x66f5ce1c, +0x66ffe843, 0x670a02aa, 0x67141d50, 0x671e3836, 0x6728535b, 0x67326ebf, 0x673c8a63, 0x6746a646, +0x6750c268, 0x675adeca, 0x6764fb6b, 0x676f184b, 0x6779356a, 0x678352c9, 0x678d7067, 0x67978e45, +0x67a1ac61, 0x67abcabd, 0x67b5e958, 0x67c00832, 0x67ca274c, 0x67d446a4, 0x67de663c, 0x67e88613, +0x67f2a629, 0x67fcc67e, 0x6806e712, 0x681107e6, 0x681b28f8, 0x68254a4a, 0x682f6bda, 0x68398daa, +0x6843afb9, 0x684dd206, 0x6857f493, 0x6862175f, 0x686c3a6a, 0x68765db3, 0x6880813c, 0x688aa504, +0x6894c90a, 0x689eed50, 0x68a911d5, 0x68b33698, 0x68bd5b9a, 0x68c780dc, 0x68d1a65c, 0x68dbcc1b, +0x68e5f218, 0x68f01855, 0x68fa3ed0, 0x6904658b, 0x690e8c84, 0x6918b3bc, 0x6922db32, 0x692d02e8, +0x69372adc, 0x6941530f, 0x694b7b81, 0x6955a431, 0x695fcd20, 0x6969f64e, 0x69741fbb, 0x697e4966, +0x69887350, 0x69929d78, 0x699cc7df, 0x69a6f285, 0x69b11d69, 0x69bb488c, 0x69c573ee, 0x69cf9f8e, +0x69d9cb6d, 0x69e3f78a, 0x69ee23e6, 0x69f85080, 0x6a027d59, 0x6a0caa71, 0x6a16d7c7, 0x6a21055b, +0x6a2b332e, 0x6a35613f, 0x6a3f8f8f, 0x6a49be1d, 0x6a53ecea, 0x6a5e1bf5, 0x6a684b3f, 0x6a727ac7, +0x6a7caa8d, 0x6a86da91, 0x6a910ad4, 0x6a9b3b56, 0x6aa56c15, 0x6aaf9d13, 0x6ab9ce50, 0x6ac3ffca, +0x6ace3183, 0x6ad8637b, 0x6ae295b0, 0x6aecc824, 0x6af6fad6, 0x6b012dc6, 0x6b0b60f4, 0x6b159461, +0x6b1fc80c, 0x6b29fbf5, 0x6b34301c, 0x6b3e6481, 0x6b489925, 0x6b52ce06, 0x6b5d0326, 0x6b673884, +0x6b716e20, 0x6b7ba3fa, 0x6b85da12, 0x6b901068, 0x6b9a46fd, 0x6ba47dcf, 0x6baeb4df, 0x6bb8ec2e, +0x6bc323ba, 0x6bcd5b85, 0x6bd7938d, 0x6be1cbd3, 0x6bec0458, 0x6bf63d1a, 0x6c00761a, 0x6c0aaf58, +0x6c14e8d4, 0x6c1f228e, 0x6c295c86, 0x6c3396bc, 0x6c3dd130, 0x6c480be1, 0x6c5246d1, 0x6c5c81fe, +0x6c66bd69, 0x6c70f912, 0x6c7b34f8, 0x6c85711d, 0x6c8fad7f, 0x6c99ea1f, 0x6ca426fd, 0x6cae6418, +0x6cb8a172, 0x6cc2df09, 0x6ccd1cdd, 0x6cd75af0, 0x6ce19940, 0x6cebd7ce, 0x6cf61699, 0x6d0055a2, +0x6d0a94e9, 0x6d14d46d, 0x6d1f142f, 0x6d29542f, 0x6d33946c, 0x6d3dd4e7, 0x6d4815a0, 0x6d525695, +0x6d5c97c9, 0x6d66d93a, 0x6d711ae9, 0x6d7b5cd5, 0x6d859eff, 0x6d8fe166, 0x6d9a240a, 0x6da466ec, +0x6daeaa0c, 0x6db8ed69, 0x6dc33104, 0x6dcd74db, 0x6dd7b8f1, 0x6de1fd44, 0x6dec41d4, 0x6df686a1, +0x6e00cbac, 0x6e0b10f5, 0x6e15567a, 0x6e1f9c3d, 0x6e29e23d, 0x6e34287b, 0x6e3e6ef6, 0x6e48b5ae, +0x6e52fca4, 0x6e5d43d7, 0x6e678b47, 0x6e71d2f4, 0x6e7c1adf, 0x6e866307, 0x6e90ab6c, 0x6e9af40e, +0x6ea53ced, 0x6eaf860a, 0x6eb9cf64, 0x6ec418fb, 0x6ece62cf, 0x6ed8ace0, 0x6ee2f72e, 0x6eed41ba, +0x6ef78c83, 0x6f01d788, 0x6f0c22cb, 0x6f166e4b, 0x6f20ba08, 0x6f2b0602, 0x6f355239, 0x6f3f9ead, +0x6f49eb5e, 0x6f54384d, 0x6f5e8578, 0x6f68d2e0, 0x6f732085, 0x6f7d6e67, 0x6f87bc86, 0x6f920ae2, +0x6f9c597b, 0x6fa6a851, 0x6fb0f763, 0x6fbb46b3, 0x6fc59640, 0x6fcfe609, 0x6fda360f, 0x6fe48652, +0x6feed6d2, 0x6ff9278f, 0x70037889, 0x700dc9bf, 0x70181b32, 0x70226ce3, 0x702cbecf, 0x703710f9, +0x7041635f, 0x704bb602, 0x705608e2, 0x70605bff, 0x706aaf58, 0x707502ee, 0x707f56c1, 0x7089aad0, +0x7093ff1c, 0x709e53a5, 0x70a8a86a, 0x70b2fd6c, 0x70bd52ab, 0x70c7a826, 0x70d1fdde, 0x70dc53d2, +0x70e6aa03, 0x70f10071, 0x70fb571b, 0x7105ae02, 0x71100525, 0x711a5c85, 0x7124b421, 0x712f0bfa, +0x7139640f, 0x7143bc61, 0x714e14ef, 0x71586dba, 0x7162c6c1, 0x716d2004, 0x71777984, 0x7181d341, +0x718c2d3a, 0x7196876f, 0x71a0e1e1, 0x71ab3c8f, 0x71b59779, 0x71bff2a0, 0x71ca4e03, 0x71d4a9a3, +0x71df057e, 0x71e96197, 0x71f3bdeb, 0x71fe1a7c, 0x72087749, 0x7212d452, 0x721d3197, 0x72278f19, +0x7231ecd7, 0x723c4ad1, 0x7246a908, 0x7251077b, 0x725b6629, 0x7265c514, 0x7270243c, 0x727a839f, +0x7284e33f, 0x728f431a, 0x7299a332, 0x72a40386, 0x72ae6416, 0x72b8c4e2, 0x72c325eb, 0x72cd872f, +0x72d7e8af, 0x72e24a6c, 0x72ecac64, 0x72f70e99, 0x73017109, 0x730bd3b6, 0x7316369f, 0x732099c3, +0x732afd24, 0x733560c0, 0x733fc499, 0x734a28ad, 0x73548cfe, 0x735ef18a, 0x73695652, 0x7373bb57, +0x737e2097, 0x73888613, 0x7392ebca, 0x739d51be, 0x73a7b7ee, 0x73b21e59, 0x73bc8500, 0x73c6ebe4, +0x73d15302, 0x73dbba5d, 0x73e621f4, 0x73f089c6, 0x73faf1d4, 0x74055a1e, 0x740fc2a3, 0x741a2b65, +0x74249462, 0x742efd9b, 0x7439670f, 0x7443d0bf, 0x744e3aab, 0x7458a4d3, 0x74630f36, 0x746d79d5, +0x7477e4af, 0x74824fc6, 0x748cbb17, 0x749726a5, 0x74a1926e, 0x74abfe73, 0x74b66ab3, 0x74c0d72f, +0x74cb43e6, 0x74d5b0d9, 0x74e01e07, 0x74ea8b71, 0x74f4f917, 0x74ff66f8, 0x7509d514, 0x7514436c, +0x751eb200, 0x752920cf, 0x75338fd9, 0x753dff1f, 0x75486ea1, 0x7552de5d, 0x755d4e56, 0x7567be89, +0x75722ef8, 0x757c9fa3, 0x75871089, 0x759181aa, 0x759bf306, 0x75a6649e, 0x75b0d671, 0x75bb4880, +0x75c5baca, 0x75d02d4f, 0x75daa00f, 0x75e5130b, 0x75ef8642, 0x75f9f9b4, 0x76046d62, 0x760ee14b, +0x7619556f, 0x7623c9ce, 0x762e3e68, 0x7638b33e, 0x7643284f, 0x764d9d9b, 0x76581322, 0x766288e4, +0x766cfee2, 0x7677751b, 0x7681eb8e, 0x768c623d, 0x7696d927, 0x76a1504d, 0x76abc7ad, 0x76b63f48, +0x76c0b71f, 0x76cb2f30, 0x76d5a77d, 0x76e02004, 0x76ea98c7, 0x76f511c4, 0x76ff8afd, 0x770a0471, +0x77147e1f, 0x771ef809, 0x7729722d, 0x7733ec8d, 0x773e6727, 0x7748e1fd, 0x77535d0d, 0x775dd858, +0x776853df, 0x7772cfa0, 0x777d4b9c, 0x7787c7d2, 0x77924444, 0x779cc0f1, 0x77a73dd8, 0x77b1bafa, +0x77bc3858, 0x77c6b5ef, 0x77d133c2, 0x77dbb1d0, 0x77e63018, 0x77f0ae9b, 0x77fb2d59, 0x7805ac52, +0x78102b85, 0x781aaaf3, 0x78252a9c, 0x782faa80, 0x783a2a9e, 0x7844aaf7, 0x784f2b8a, 0x7859ac59, +0x78642d62, 0x786eaea5, 0x78793024, 0x7883b1dd, 0x788e33d0, 0x7898b5fe, 0x78a33867, 0x78adbb0b, +0x78b83de9, 0x78c2c101, 0x78cd4454, 0x78d7c7e2, 0x78e24baa, 0x78eccfad, 0x78f753ea, 0x7901d862, +0x790c5d15, 0x7916e202, 0x79216729, 0x792bec8b, 0x79367227, 0x7940f7fe, 0x794b7e0f, 0x7956045b, +0x79608ae1, 0x796b11a1, 0x7975989c, 0x79801fd1, 0x798aa741, 0x79952eeb, 0x799fb6d0, 0x79aa3eee, +0x79b4c748, 0x79bf4fdb, 0x79c9d8a9, 0x79d461b1, 0x79deeaf4, 0x79e97470, 0x79f3fe27, 0x79fe8819, +0x7a091244, 0x7a139caa, 0x7a1e274a, 0x7a28b225, 0x7a333d39, 0x7a3dc888, 0x7a485411, 0x7a52dfd4, +0x7a5d6bd2, 0x7a67f809, 0x7a72847b, 0x7a7d1127, 0x7a879e0d, 0x7a922b2e, 0x7a9cb888, 0x7aa7461d, +0x7ab1d3eb, 0x7abc61f4, 0x7ac6f037, 0x7ad17eb4, 0x7adc0d6b, 0x7ae69c5c, 0x7af12b87, 0x7afbbaec, +0x7b064a8b, 0x7b10da64, 0x7b1b6a78, 0x7b25fac5, 0x7b308b4c, 0x7b3b1c0e, 0x7b45ad09, 0x7b503e3e, +0x7b5acfad, 0x7b656156, 0x7b6ff339, 0x7b7a8556, 0x7b8517ad, 0x7b8faa3e, 0x7b9a3d09, 0x7ba4d00d, +0x7baf634c, 0x7bb9f6c4, 0x7bc48a76, 0x7bcf1e62, 0x7bd9b288, 0x7be446e8, 0x7beedb82, 0x7bf97055, +0x7c040562, 0x7c0e9aa9, 0x7c19302a, 0x7c23c5e5, 0x7c2e5bd9, 0x7c38f207, 0x7c43886f, 0x7c4e1f10, +0x7c58b5ec, 0x7c634d01, 0x7c6de450, 0x7c787bd8, 0x7c83139a, 0x7c8dab96, 0x7c9843cb, 0x7ca2dc3a, +0x7cad74e3, 0x7cb80dc6, 0x7cc2a6e2, 0x7ccd4037, 0x7cd7d9c7, 0x7ce27390, 0x7ced0d92, 0x7cf7a7ce, +0x7d024244, 0x7d0cdcf3, 0x7d1777dc, 0x7d2212fe, 0x7d2cae5a, 0x7d3749ef, 0x7d41e5be, 0x7d4c81c7, +0x7d571e08, 0x7d61ba84, 0x7d6c5739, 0x7d76f427, 0x7d81914f, 0x7d8c2eb0, 0x7d96cc4b, 0x7da16a1f, +0x7dac082d, 0x7db6a673, 0x7dc144f4, 0x7dcbe3ae, 0x7dd682a1, 0x7de121cd, 0x7debc133, 0x7df660d2, +0x7e0100ab, 0x7e0ba0bd, 0x7e164108, 0x7e20e18d, 0x7e2b824b, 0x7e362342, 0x7e40c472, 0x7e4b65dc, +0x7e56077f, 0x7e60a95b, 0x7e6b4b71, 0x7e75edc0, 0x7e809048, 0x7e8b3309, 0x7e95d603, 0x7ea07937, +0x7eab1ca4, 0x7eb5c04a, 0x7ec06429, 0x7ecb0842, 0x7ed5ac93, 0x7ee0511e, 0x7eeaf5e2, 0x7ef59adf, +0x7f004015, 0x7f0ae584, 0x7f158b2c, 0x7f20310e, 0x7f2ad728, 0x7f357d7c, 0x7f402409, 0x7f4acace, +0x7f5571cd, 0x7f601905, 0x7f6ac076, 0x7f75681f, 0x7f801002, 0x7f8ab81e, 0x7f956073, 0x7fa00901, +0x7faab1c7, 0x7fb55ac7, 0x7fc00400, 0x7fcaad71, 0x7fd5571c, 0x7fe00100, 0x7feaab1c, 0x7ff55571, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, +0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_aa_cs_data[] = { +0x00006dc2, 0x000070dc, 0x0000798d, 0x00007ddd, 0x00007f6d, 0x00007fe4, 0x00007ffc, 0x00007fff,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_aa_ca_data[] = { +0xffffbe26, 0xffffc39f, 0xffffd7e4, 0xffffe8b8, 0xfffff3e5, 0xfffffac2, 0xfffffe2f, 0xffffff87,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_win_data[] = { +0x00000421, 0x00000db8, 0x000019c7, 0x000029ad, 0x00003fff, 0x00006246, 0x00009ee0, 0x00012a7d, +0x0003df40, 0xfffbc63e, 0xfffe7b01, 0xffff069e, 0xffff4338, 0xffff657e, 0xffff7bd0, 0xffff8bb6, +0xffff97c5, 0xffffa15c, 0xffffa947, 0xffffb006, 0xffffb5eb, 0xffffbb30, 0xffffc000, 0xffffc47a, +0xffffc8b7, 0xffffccca, 0xffffd0c5, 0xffffd4b9, 0xffffd8b4, 0xffffdcc8, 0xffffe104, 0xffffe57e, +0xffffea4e, 0xffffef94, 0xfffff579, 0xfffffc37, 0x00000421, 0x00000db8, 0x000019c7, 0x000029ad, +0x00003fff, 0x00006246, 0x00009ee0, 0x00012a7d, 0x0003df40, 0xfffbc63e, 0xfffe7b01, 0xffff069e, +0xffff4338, 0xffff657e, 0xffff7bd0, 0xffff8bb6, 0xffff97c5, 0xffffa15c, 0xffffa932, 0xffffaf55, +0xffffb41e, 0xffffb7d9, 0xffffbabb, 0xffffbce5, 0xffffbf02, 0xffffc45d, 0xffffcd2e, 0xffffd901, +0xffffe74d, 0xfffff772, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000db8, 0x00003fff, 0x00012a7d, 0xfffe7b01, 0xffff657e, 0xffff97c5, 0xffffb006, 0xffffc000, +0xffffccca, 0xffffd8b4, 0xffffe57e, 0xfffff579, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00002698, 0x0000bba3, 0x00037d32, 0xfffb73f7, 0xfffe3b01, 0xfffedad6, +0xffff2b2b, 0xffff58c3, 0xffff7566, 0xffff88e3, 0xffff96df, 0xffffa145, 0xffffa947, 0xffffb006, +0xffffb5eb, 0xffffbb30, 0xffffc000, 0xffffc47a, 0xffffc8b7, 0xffffccca, 0xffffd0c5, 0xffffd4b9, +0xffffd8b4, 0xffffdcc8, 0xffffe104, 0xffffe57e, 0xffffea4e, 0xffffef94, 0xfffff579, 0xfffffc37,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_COS9_data[] = { +0x00008000, 0x00007e0e, 0x00007847, 0x00006ed9, 0x0000620d, 0x00005246, 0x00004000, 0x00002bc7, +0x0000163a,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_tfcos36_data[] = { +0x0000403e, 0x00004241, 0x0000469d, 0x00004e21, 0x00005a82, 0x00006f94, 0x0000976f, 0x0000f746, +0x0002de51,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_tfcos12_data[] = { +0x00004241, 0x00005a82, 0x0000f746,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_cos9_data[] = { +0x00007847, 0xffffe9c6, 0xffff9df3,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_cos18_data[] = { +0x00007e0e, 0xffffd439, 0xffffadba,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_COS1_data[] = { +0x00004deb, 0xffff89bf, 0xffffef4b, 0x00007ee7, 0xffffcf05, 0xffff9a74, 0x000030fb, 0xffff89bf, +0x00007641, 0xffffcf05, 0xffffcf05, 0x00007641, 0x000010b5, 0xffffcf05, 0x00004deb, 0xffff9a74, +0x00007641, 0xffff8119, 0xffffef4b, 0x000030fb, 0xffffb215, 0x0000658c, 0xffff89bf, 0x00007ee7, +0xffffcf05, 0x00007641, 0xffff89bf, 0x000030fb, 0x000030fb, 0xffff89bf, 0xffffb215, 0x00007641, +0x000010b5, 0xffff8119, 0x000030fb, 0x0000658c, 0xffff9a74, 0x000030fb, 0x00007ee7, 0x000010b5, +0xffff89bf, 0xffffb215, 0xffff89bf, 0xffffcf05, 0x000030fb, 0x00007641, 0x00007641, 0x000030fb, +0xffff8119, 0xffff89bf, 0xffff9a74, 0xffffb215, 0xffffcf05, 0xffffef4b, 0xffff8119, 0xffff89bf, +0xffff9a74, 0xffffb215, 0xffffcf05, 0xffffef4b, 0xffff89bf, 0xffffcf05, 0x000030fb, 0x00007641, +0x00007641, 0x000030fb, 0xffff9a74, 0x000030fb, 0x00007ee7, 0x000010b5, 0xffff89bf, 0xffffb215,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_win1_data[] = { +0x00000421, 0xfffff248, 0x000019c7, 0xffffd653, 0x00003fff, 0xffff9dba, 0x00009ee0, 0xfffed583, +0x0003df40, 0x000439c2, 0xfffe7b01, 0x0000f962, 0xffff4338, 0x00009a82, 0xffff7bd0, 0x0000744a, +0xffff97c5, 0x00005ea4, 0xffffa947, 0x00004ffa, 0xffffb5eb, 0x000044d0, 0xffffc000, 0x00003b86, +0xffffc8b7, 0x00003336, 0xffffd0c5, 0x00002b47, 0xffffd8b4, 0x00002338, 0xffffe104, 0x00001a82, +0xffffea4e, 0x0000106c, 0xfffff579, 0x000003c9, 0x00000421, 0xfffff248, 0x000019c7, 0xffffd653, +0x00003fff, 0xffff9dba, 0x00009ee0, 0xfffed583, 0x0003df40, 0x000439c2, 0xfffe7b01, 0x0000f962, +0xffff4338, 0x00009a82, 0xffff7bd0, 0x0000744a, 0xffff97c5, 0x00005ea4, 0xffffa932, 0x000050ab, +0xffffb41e, 0x00004827, 0xffffbabb, 0x0000431b, 0xffffbf02, 0x00003ba3, 0xffffcd2e, 0x000026ff, +0xffffe74d, 0x0000088e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000db8, 0xffffc001, 0x00012a7d, 0x000184ff, 0xffff657e, 0x0000683b, 0xffffb006, 0x00004000, +0xffffccca, 0x0000274c, 0xffffe57e, 0x00000a87, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00002698, 0xffff445d, 0x00037d32, 0x00048c09, 0xfffe3b01, 0x0001252a, +0xffff2b2b, 0x0000a73d, 0xffff7566, 0x0000771d, 0xffff96df, 0x00005ebb, 0xffffa947, 0x00004ffa, +0xffffb5eb, 0x000044d0, 0xffffc000, 0x00003b86, 0xffffc8b7, 0x00003336, 0xffffd0c5, 0x00002b47, +0xffffd8b4, 0x00002338, 0xffffe104, 0x00001a82, 0xffffea4e, 0x0000106c, 0xfffff579, 0x000003c9,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_tan1_1_data[] = { +0x00000000, 0x00001b0c, 0x00002ed9, 0x00003fff, 0x00005126, 0x000064f3, 0x00007fff, 0x0000aed9, +0x00012ed9, 0x7fffffff, 0xffff5127, 0xffffd127, 0x00000000, 0x00001b0c, 0x00002ed9, 0x00003fff,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_tan2_1_data[] = { +0x00008000, 0x000064f3, 0x00005126, 0x00004000, 0x00002ed9, 0x00001b0c, 0x00000000, 0xffffd127, +0xffff5127, 0x80000000, 0x00012ed9, 0x0000aed9, 0x00008000, 0x000064f3, 0x00005126, 0x00004000,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_tan1_2_data[] = { +0x00000000, 0x00002640, 0x00004241, 0x00005a82, 0x000072c2, 0x00008ec3, 0x0000b504, 0x0000f746, +0x0001ac4b, 0x7fffffff, 0xffff08ba, 0xffffbdbf, 0x00000000, 0x00002640, 0x00004241, 0x00005a82,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_tan2_2_data[] = { +0x0000b504, 0x00008ec3, 0x000072c2, 0x00005a82, 0x00004241, 0x00002640, 0x00000000, 0xffffbdbf, +0xffff08ba, 0x80000000, 0x0001ac4b, 0x0000f746, 0x0000b504, 0x00008ec3, 0x000072c2, 0x00005a82,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_pow1_1_data[] = { +0x00008000, 0x00006ba2, 0x00008000, 0x00005a82, 0x00008000, 0x00004c1b, 0x00008000, 0x00004000, +0x00008000, 0x000035d1, 0x00008000, 0x00002d41, 0x00008000, 0x0000260d, 0x00008000, 0x00002000, +0x00008000, 0x00005a82, 0x00008000, 0x00003fff, 0x00008000, 0x00002d41, 0x00008000, 0x00001fff, +0x00008000, 0x000016a0, 0x00008000, 0x00000fff, 0x00008000, 0x00000b50, 0x00008000, 0x000007ff,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_pow2_1_data[] = { +0x00008000, 0x00008000, 0x00006ba2, 0x00008000, 0x00005a82, 0x00008000, 0x00004c1b, 0x00008000, +0x00004000, 0x00008000, 0x000035d1, 0x00008000, 0x00002d41, 0x00008000, 0x0000260d, 0x00008000, +0x00008000, 0x00008000, 0x00005a82, 0x00008000, 0x00003fff, 0x00008000, 0x00002d41, 0x00008000, +0x00001fff, 0x00008000, 0x000016a0, 0x00008000, 0x00000fff, 0x00008000, 0x00000b50, 0x00008000,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_pow1_2_data[] = { +0x0000b504, 0x00009837, 0x0000b504, 0x00008000, 0x0000b504, 0x00006ba2, 0x0000b504, 0x00005a82, +0x0000b504, 0x00004c1b, 0x0000b504, 0x00004000, 0x0000b504, 0x000035d1, 0x0000b504, 0x00002d41, +0x0000b504, 0x00008000, 0x0000b504, 0x00005a82, 0x0000b504, 0x00003fff, 0x0000b504, 0x00002d41, +0x0000b504, 0x00001fff, 0x0000b504, 0x000016a0, 0x0000b504, 0x00000fff, 0x0000b504, 0x00000b50,}; +#endif +#ifdef USE_DATA_TABLES +static long mpeg3_pow2_2_data[] = { +0x0000b504, 0x0000b504, 0x00009837, 0x0000b504, 0x00008000, 0x0000b504, 0x00006ba2, 0x0000b504, +0x00005a82, 0x0000b504, 0x00004c1b, 0x0000b504, 0x00004000, 0x0000b504, 0x000035d1, 0x0000b504, +0x0000b504, 0x0000b504, 0x00008000, 0x0000b504, 0x00005a82, 0x0000b504, 0x00003fff, 0x0000b504, +0x00002d41, 0x0000b504, 0x00001fff, 0x0000b504, 0x000016a0, 0x0000b504, 0x00000fff, 0x0000b504,}; +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/audio/header.c b/core/multimedia/opieplayer/libmpeg3/audio/header.c new file mode 100644 index 0000000..02b5e7c --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/header.c @@ -0,0 +1,163 @@ +#include "mpeg3audio.h" +#include "tables.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" + +#include + +/* Return 1 if the head check doesn't find a header. */ +int mpeg3audio_head_check(unsigned long head) +{ + if((head & 0xffe00000) != 0xffe00000) return 1; + if(!((head >> 17) & 3)) return 1; + if(((head >> 12) & 0xf) == 0xf) return 1; + if(!((head >> 12) & 0xf)) return 1; + if(((head >> 10) & 0x3) == 0x3 ) return 1; + if(((head >> 19) & 1) == 1 && ((head >> 17) & 3) == 3 && ((head >> 16) & 1) == 1) + return 1; + if((head & 0xffff0000) == 0xfffe0000) return 1; + + return 0; +} + +int mpeg3audio_decode_header(mpeg3audio_t *audio) +{ + if(audio->newhead & (1 << 20)) + { + audio->lsf = (audio->newhead & (1 << 19)) ? 0x0 : 0x1; + audio->mpeg35 = 0; + } + else + { + audio->lsf = 1; + audio->mpeg35 = 1; + } + + audio->layer = 4 - ((audio->newhead >> 17) & 3); + if(audio->mpeg35) + audio->sampling_frequency_code = 6 + ((audio->newhead >> 10) & 0x3); + else + audio->sampling_frequency_code = ((audio->newhead >> 10) & 0x3) + (audio->lsf * 3); + + audio->error_protection = ((audio->newhead >> 16) & 0x1) ^ 0x1; + + audio->bitrate_index = ((audio->newhead >> 12) & 0xf); + audio->padding = ((audio->newhead >> 9) & 0x1); + audio->extension = ((audio->newhead >> 8) & 0x1); + audio->mode = ((audio->newhead >> 6) & 0x3); + audio->mode_ext = ((audio->newhead >> 4) & 0x3); + audio->copyright = ((audio->newhead >> 3) & 0x1); + audio->original = ((audio->newhead >> 2) & 0x1); + audio->emphasis = audio->newhead & 0x3; + audio->channels = (audio->mode == MPG_MD_MONO) ? 1 : 2; + if(audio->channels > 1) + audio->single = -1; + else + audio->single = 3; + + audio->prev_framesize = audio->framesize; + + if(!audio->bitrate_index) return 1; + audio->bitrate = 1000 * mpeg3_tabsel_123[audio->lsf][audio->layer - 1][audio->bitrate_index]; + + switch(audio->layer) + { + case 1: + audio->framesize = (long)mpeg3_tabsel_123[audio->lsf][0][audio->bitrate_index] * 12000; + audio->framesize /= mpeg3_freqs[audio->sampling_frequency_code]; + audio->framesize = ((audio->framesize + audio->padding) << 2) - 4; + break; + case 2: + audio->framesize = (long)mpeg3_tabsel_123[audio->lsf][1][audio->bitrate_index] * 144000; + audio->framesize /= mpeg3_freqs[audio->sampling_frequency_code]; + audio->framesize += audio->padding - 4; + break; + case 3: + if(audio->lsf) + audio->ssize = (audio->channels == 1) ? 9 : 17; + else + audio->ssize = (audio->channels == 1) ? 17 : 32; + if(audio->error_protection) + audio->ssize += 2; + audio->framesize = (long)mpeg3_tabsel_123[audio->lsf][2][audio->bitrate_index] * 144000; + audio->framesize /= mpeg3_freqs[audio->sampling_frequency_code] << (audio->lsf); + audio->framesize = audio->framesize + audio->padding - 4; + break; + default: + return 1; + } + + if(audio->framesize > MAXFRAMESIZE) return 1; + + return 0; +} + +int mpeg3audio_read_frame_body(mpeg3audio_t *audio) +{ + int i; + for(i = 0; i < audio->framesize; i++) + { + audio->bsbuf[i] = mpeg3bits_getbits(audio->astream, 8); + } + return 0; +} + +/* Seek to the start of the previous header */ +int mpeg3audio_prev_header(mpeg3audio_t *audio) +{ + int result = 0, i, len = (int)audio->avg_framesize; + + for(i = 0; i < len && !result; i++) + { + mpeg3bits_getbits_reverse(audio->astream, 8); + } +/* Get reading in the forward direction again. */ + result |= mpeg3bits_refill(audio->astream); + return result; +} + +/* Read the next header */ +int mpeg3audio_read_header(mpeg3audio_t *audio) +{ + unsigned int code; + int i; + int attempt = 0; + int result = 0; + + switch(audio->format) + { + case AUDIO_AC3: + result = mpeg3audio_read_ac3_header(audio); + break; + + case AUDIO_MPEG: +/* Layer 1 not supported */ + if(audio->layer == 1) + { + fprintf(stderr, "mpeg3audio_new: layer 1 not supported\n"); + result = 1; + } + audio->newhead = mpeg3bits_showbits(audio->astream, 32); + if(!mpeg3bits_eof(audio->astream) && + (mpeg3audio_head_check(audio->newhead) || mpeg3audio_decode_header(audio))) + { + do + { + attempt++; + mpeg3bits_getbyte_noptr(audio->astream); + audio->newhead = mpeg3bits_showbits(audio->astream, 32); + }while(!mpeg3bits_eof(audio->astream) && + attempt < 65536 && + (mpeg3audio_head_check(audio->newhead) || mpeg3audio_decode_header(audio))); + } + +/* Skip the 4 bytes containing the header */ + mpeg3bits_getbits(audio->astream, 32); + break; + + case AUDIO_PCM: + mpeg3audio_read_pcm_header(audio); + break; + } + return mpeg3bits_eof(audio->astream); +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/huffman.h b/core/multimedia/opieplayer/libmpeg3/audio/huffman.h new file mode 100644 index 0000000..a9c8fff --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/huffman.h @@ -0,0 +1,355 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef HUFFMAN_H +#define HUFFMAN_H + +/* + * huffman tables ... recalcualted to work with my optimzed + * decoder scheme (MH) + * + * probably we could save a few bytes of memory, because the + * smaller tables are often the part of a bigger table + */ + +struct newhuff +{ + unsigned int linbits; + short *table; +}; + +static short mpeg3_tab0[] = +{ + 0 +}; + +static short mpeg3_tab1[] = +{ + -5, -3, -1, 17, 1, 16, 0 +}; + +static short mpeg3_tab2[] = +{ + -15, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 17, -1, 1, + 16, 0 +}; + +static short mpeg3_tab3[] = +{ + -13, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 16, 17, -1, + 1, 0 +}; + +static short mpeg3_tab5[] = +{ + -29, -25, -23, -15, -7, -5, -3, -1, 51, 35, 50, 49, -3, -1, 19, + 3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16, + 0 +}; + +static short mpeg3_tab6[] = +{ + -25, -19, -13, -9, -5, -3, -1, 51, 3, 35, -1, 50, 48, -1, 19, + 49, -3, -1, 34, 2, 18, -3, -1, 33, 32, 1, -1, 17, -1, 16, + 0 +}; + +static short mpeg3_tab7[] = +{ + -69, -65, -57, -39, -29, -17, -11, -7, -3, -1, 85, 69, -1, 84, 83, + -1, 53, 68, -3, -1, 37, 82, 21, -5, -1, 81, -1, 5, 52, -1, + 80, -1, 67, 51, -5, -3, -1, 36, 66, 20, -1, 65, 64, -11, -7, + -3, -1, 4, 35, -1, 50, 3, -1, 19, 49, -3, -1, 48, 34, 18, + -5, -1, 33, -1, 2, 32, 17, -1, 1, 16, 0 +}; + +static short mpeg3_tab8[] = +{ + -65, -63, -59, -45, -31, -19, -13, -7, -5, -3, -1, 85, 84, 69, 83, + -3, -1, 53, 68, 37, -3, -1, 82, 5, 21, -5, -1, 81, -1, 52, + 67, -3, -1, 80, 51, 36, -5, -3, -1, 66, 20, 65, -3, -1, 4, + 64, -1, 35, 50, -9, -7, -3, -1, 19, 49, -1, 3, 48, 34, -1, + 2, 32, -1, 18, 33, 17, -3, -1, 1, 16, 0 +}; + +static short mpeg3_tab9[] = +{ + -63, -53, -41, -29, -19, -11, -5, -3, -1, 85, 69, 53, -1, 83, -1, + 84, 5, -3, -1, 68, 37, -1, 82, 21, -3, -1, 81, 52, -1, 67, + -1, 80, 4, -7, -3, -1, 36, 66, -1, 51, 64, -1, 20, 65, -5, + -3, -1, 35, 50, 19, -1, 49, -1, 3, 48, -5, -3, -1, 34, 2, + 18, -1, 33, 32, -3, -1, 17, 1, -1, 16, 0 +}; + +static short mpeg3_tab10[] = +{ +-125,-121,-111, -83, -55, -35, -21, -13, -7, -3, -1, 119, 103, -1, 118, + 87, -3, -1, 117, 102, 71, -3, -1, 116, 86, -1, 101, 55, -9, -3, + -1, 115, 70, -3, -1, 85, 84, 99, -1, 39, 114, -11, -5, -3, -1, + 100, 7, 112, -1, 98, -1, 69, 53, -5, -1, 6, -1, 83, 68, 23, + -17, -5, -1, 113, -1, 54, 38, -5, -3, -1, 37, 82, 21, -1, 81, + -1, 52, 67, -3, -1, 22, 97, -1, 96, -1, 5, 80, -19, -11, -7, + -3, -1, 36, 66, -1, 51, 4, -1, 20, 65, -3, -1, 64, 35, -1, + 50, 3, -3, -1, 19, 49, -1, 48, 34, -7, -3, -1, 18, 33, -1, + 2, 32, 17, -1, 1, 16, 0 +}; + +static short mpeg3_tab11[] = +{ +-121,-113, -89, -59, -43, -27, -17, -7, -3, -1, 119, 103, -1, 118, 117, + -3, -1, 102, 71, -1, 116, -1, 87, 85, -5, -3, -1, 86, 101, 55, + -1, 115, 70, -9, -7, -3, -1, 69, 84, -1, 53, 83, 39, -1, 114, + -1, 100, 7, -5, -1, 113, -1, 23, 112, -3, -1, 54, 99, -1, 96, + -1, 68, 37, -13, -7, -5, -3, -1, 82, 5, 21, 98, -3, -1, 38, + 6, 22, -5, -1, 97, -1, 81, 52, -5, -1, 80, -1, 67, 51, -1, + 36, 66, -15, -11, -7, -3, -1, 20, 65, -1, 4, 64, -1, 35, 50, + -1, 19, 49, -5, -3, -1, 3, 48, 34, 33, -5, -1, 18, -1, 2, + 32, 17, -3, -1, 1, 16, 0 +}; + +static short mpeg3_tab12[] = +{ +-115, -99, -73, -45, -27, -17, -9, -5, -3, -1, 119, 103, 118, -1, 87, + 117, -3, -1, 102, 71, -1, 116, 101, -3, -1, 86, 55, -3, -1, 115, + 85, 39, -7, -3, -1, 114, 70, -1, 100, 23, -5, -1, 113, -1, 7, + 112, -1, 54, 99, -13, -9, -3, -1, 69, 84, -1, 68, -1, 6, 5, + -1, 38, 98, -5, -1, 97, -1, 22, 96, -3, -1, 53, 83, -1, 37, + 82, -17, -7, -3, -1, 21, 81, -1, 52, 67, -5, -3, -1, 80, 4, + 36, -1, 66, 20, -3, -1, 51, 65, -1, 35, 50, -11, -7, -5, -3, + -1, 64, 3, 48, 19, -1, 49, 34, -1, 18, 33, -7, -5, -3, -1, + 2, 32, 0, 17, -1, 1, 16 +}; + +static short mpeg3_tab13[] = +{ +-509,-503,-475,-405,-333,-265,-205,-153,-115, -83, -53, -35, -21, -13, -9, + -7, -5, -3, -1, 254, 252, 253, 237, 255, -1, 239, 223, -3, -1, 238, + 207, -1, 222, 191, -9, -3, -1, 251, 206, -1, 220, -1, 175, 233, -1, + 236, 221, -9, -5, -3, -1, 250, 205, 190, -1, 235, 159, -3, -1, 249, + 234, -1, 189, 219, -17, -9, -3, -1, 143, 248, -1, 204, -1, 174, 158, + -5, -1, 142, -1, 127, 126, 247, -5, -1, 218, -1, 173, 188, -3, -1, + 203, 246, 111, -15, -7, -3, -1, 232, 95, -1, 157, 217, -3, -1, 245, + 231, -1, 172, 187, -9, -3, -1, 79, 244, -3, -1, 202, 230, 243, -1, + 63, -1, 141, 216, -21, -9, -3, -1, 47, 242, -3, -1, 110, 156, 15, + -5, -3, -1, 201, 94, 171, -3, -1, 125, 215, 78, -11, -5, -3, -1, + 200, 214, 62, -1, 185, -1, 155, 170, -1, 31, 241, -23, -13, -5, -1, + 240, -1, 186, 229, -3, -1, 228, 140, -1, 109, 227, -5, -1, 226, -1, + 46, 14, -1, 30, 225, -15, -7, -3, -1, 224, 93, -1, 213, 124, -3, + -1, 199, 77, -1, 139, 184, -7, -3, -1, 212, 154, -1, 169, 108, -1, + 198, 61, -37, -21, -9, -5, -3, -1, 211, 123, 45, -1, 210, 29, -5, + -1, 183, -1, 92, 197, -3, -1, 153, 122, 195, -7, -5, -3, -1, 167, + 151, 75, 209, -3, -1, 13, 208, -1, 138, 168, -11, -7, -3, -1, 76, + 196, -1, 107, 182, -1, 60, 44, -3, -1, 194, 91, -3, -1, 181, 137, + 28, -43, -23, -11, -5, -1, 193, -1, 152, 12, -1, 192, -1, 180, 106, + -5, -3, -1, 166, 121, 59, -1, 179, -1, 136, 90, -11, -5, -1, 43, + -1, 165, 105, -1, 164, -1, 120, 135, -5, -1, 148, -1, 119, 118, 178, + -11, -3, -1, 27, 177, -3, -1, 11, 176, -1, 150, 74, -7, -3, -1, + 58, 163, -1, 89, 149, -1, 42, 162, -47, -23, -9, -3, -1, 26, 161, + -3, -1, 10, 104, 160, -5, -3, -1, 134, 73, 147, -3, -1, 57, 88, + -1, 133, 103, -9, -3, -1, 41, 146, -3, -1, 87, 117, 56, -5, -1, + 131, -1, 102, 71, -3, -1, 116, 86, -1, 101, 115, -11, -3, -1, 25, + 145, -3, -1, 9, 144, -1, 72, 132, -7, -5, -1, 114, -1, 70, 100, + 40, -1, 130, 24, -41, -27, -11, -5, -3, -1, 55, 39, 23, -1, 113, + -1, 85, 7, -7, -3, -1, 112, 54, -1, 99, 69, -3, -1, 84, 38, + -1, 98, 53, -5, -1, 129, -1, 8, 128, -3, -1, 22, 97, -1, 6, + 96, -13, -9, -5, -3, -1, 83, 68, 37, -1, 82, 5, -1, 21, 81, + -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -19, -11, + -5, -1, 65, -1, 4, 64, -3, -1, 35, 50, 19, -3, -1, 49, 3, + -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, + 0 +}; + +static short mpeg3_tab15[] = +{ +-495,-445,-355,-263,-183,-115, -77, -43, -27, -13, -7, -3, -1, 255, 239, + -1, 254, 223, -1, 238, -1, 253, 207, -7, -3, -1, 252, 222, -1, 237, + 191, -1, 251, -1, 206, 236, -7, -3, -1, 221, 175, -1, 250, 190, -3, + -1, 235, 205, -1, 220, 159, -15, -7, -3, -1, 249, 234, -1, 189, 219, + -3, -1, 143, 248, -1, 204, 158, -7, -3, -1, 233, 127, -1, 247, 173, + -3, -1, 218, 188, -1, 111, -1, 174, 15, -19, -11, -3, -1, 203, 246, + -3, -1, 142, 232, -1, 95, 157, -3, -1, 245, 126, -1, 231, 172, -9, + -3, -1, 202, 187, -3, -1, 217, 141, 79, -3, -1, 244, 63, -1, 243, + 216, -33, -17, -9, -3, -1, 230, 47, -1, 242, -1, 110, 240, -3, -1, + 31, 241, -1, 156, 201, -7, -3, -1, 94, 171, -1, 186, 229, -3, -1, + 125, 215, -1, 78, 228, -15, -7, -3, -1, 140, 200, -1, 62, 109, -3, + -1, 214, 227, -1, 155, 185, -7, -3, -1, 46, 170, -1, 226, 30, -5, + -1, 225, -1, 14, 224, -1, 93, 213, -45, -25, -13, -7, -3, -1, 124, + 199, -1, 77, 139, -1, 212, -1, 184, 154, -7, -3, -1, 169, 108, -1, + 198, 61, -1, 211, 210, -9, -5, -3, -1, 45, 13, 29, -1, 123, 183, + -5, -1, 209, -1, 92, 208, -1, 197, 138, -17, -7, -3, -1, 168, 76, + -1, 196, 107, -5, -1, 182, -1, 153, 12, -1, 60, 195, -9, -3, -1, + 122, 167, -1, 166, -1, 192, 11, -1, 194, -1, 44, 91, -55, -29, -15, + -7, -3, -1, 181, 28, -1, 137, 152, -3, -1, 193, 75, -1, 180, 106, + -5, -3, -1, 59, 121, 179, -3, -1, 151, 136, -1, 43, 90, -11, -5, + -1, 178, -1, 165, 27, -1, 177, -1, 176, 105, -7, -3, -1, 150, 74, + -1, 164, 120, -3, -1, 135, 58, 163, -17, -7, -3, -1, 89, 149, -1, + 42, 162, -3, -1, 26, 161, -3, -1, 10, 160, 104, -7, -3, -1, 134, + 73, -1, 148, 57, -5, -1, 147, -1, 119, 9, -1, 88, 133, -53, -29, + -13, -7, -3, -1, 41, 103, -1, 118, 146, -1, 145, -1, 25, 144, -7, + -3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 71, -7, + -3, -1, 40, 130, -1, 24, 129, -7, -3, -1, 116, 8, -1, 128, 86, + -3, -1, 101, 55, -1, 115, 70, -17, -7, -3, -1, 39, 114, -1, 100, + 23, -3, -1, 85, 113, -3, -1, 7, 112, 54, -7, -3, -1, 99, 69, + -1, 84, 38, -3, -1, 98, 22, -3, -1, 6, 96, 53, -33, -19, -9, + -5, -1, 97, -1, 83, 68, -1, 37, 82, -3, -1, 21, 81, -3, -1, + 5, 80, 52, -7, -3, -1, 67, 36, -1, 66, 51, -1, 65, -1, 20, + 4, -9, -3, -1, 35, 50, -3, -1, 64, 3, 19, -3, -1, 49, 48, + 34, -9, -7, -3, -1, 18, 33, -1, 2, 32, 17, -3, -1, 1, 16, + 0 +}; + +static short mpeg3_tab16[] = +{ +-509,-503,-461,-323,-103, -37, -27, -15, -7, -3, -1, 239, 254, -1, 223, + 253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 175, -1, 250, 159, -3, + -1, 249, 248, 143, -7, -3, -1, 127, 247, -1, 111, 246, 255, -9, -5, + -3, -1, 95, 245, 79, -1, 244, 243, -53, -1, 240, -1, 63, -29, -19, + -13, -7, -5, -1, 206, -1, 236, 221, 222, -1, 233, -1, 234, 217, -1, + 238, -1, 237, 235, -3, -1, 190, 205, -3, -1, 220, 219, 174, -11, -5, + -1, 204, -1, 173, 218, -3, -1, 126, 172, 202, -5, -3, -1, 201, 125, + 94, 189, 242, -93, -5, -3, -1, 47, 15, 31, -1, 241, -49, -25, -13, + -5, -1, 158, -1, 188, 203, -3, -1, 142, 232, -1, 157, 231, -7, -3, + -1, 187, 141, -1, 216, 110, -1, 230, 156, -13, -7, -3, -1, 171, 186, + -1, 229, 215, -1, 78, -1, 228, 140, -3, -1, 200, 62, -1, 109, -1, + 214, 155, -19, -11, -5, -3, -1, 185, 170, 225, -1, 212, -1, 184, 169, + -5, -1, 123, -1, 183, 208, 227, -7, -3, -1, 14, 224, -1, 93, 213, + -3, -1, 124, 199, -1, 77, 139, -75, -45, -27, -13, -7, -3, -1, 154, + 108, -1, 198, 61, -3, -1, 92, 197, 13, -7, -3, -1, 138, 168, -1, + 153, 76, -3, -1, 182, 122, 60, -11, -5, -3, -1, 91, 137, 28, -1, + 192, -1, 152, 121, -1, 226, -1, 46, 30, -15, -7, -3, -1, 211, 45, + -1, 210, 209, -5, -1, 59, -1, 151, 136, 29, -7, -3, -1, 196, 107, + -1, 195, 167, -1, 44, -1, 194, 181, -23, -13, -7, -3, -1, 193, 12, + -1, 75, 180, -3, -1, 106, 166, 179, -5, -3, -1, 90, 165, 43, -1, + 178, 27, -13, -5, -1, 177, -1, 11, 176, -3, -1, 105, 150, -1, 74, + 164, -5, -3, -1, 120, 135, 163, -3, -1, 58, 89, 42, -97, -57, -33, + -19, -11, -5, -3, -1, 149, 104, 161, -3, -1, 134, 119, 148, -5, -3, + -1, 73, 87, 103, 162, -5, -1, 26, -1, 10, 160, -3, -1, 57, 147, + -1, 88, 133, -9, -3, -1, 41, 146, -3, -1, 118, 9, 25, -5, -1, + 145, -1, 144, 72, -3, -1, 132, 117, -1, 56, 131, -21, -11, -5, -3, + -1, 102, 40, 130, -3, -1, 71, 116, 24, -3, -1, 129, 128, -3, -1, + 8, 86, 55, -9, -5, -1, 115, -1, 101, 70, -1, 39, 114, -5, -3, + -1, 100, 85, 7, 23, -23, -13, -5, -1, 113, -1, 112, 54, -3, -1, + 99, 69, -1, 84, 38, -3, -1, 98, 22, -1, 97, -1, 6, 96, -9, + -5, -1, 83, -1, 53, 68, -1, 37, 82, -1, 81, -1, 21, 5, -33, + -23, -13, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, + -5, -1, 65, -1, 4, 64, -1, 35, 50, -3, -1, 19, 49, -3, -1, + 3, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, + 0 +}; + +static short mpeg3_tab24[] = +{ +-451,-117, -43, -25, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1, + 207, 252, -1, 191, 251, -5, -1, 250, -1, 175, 159, -1, 249, 248, -9, + -5, -3, -1, 143, 127, 247, -1, 111, 246, -3, -1, 95, 245, -1, 79, + 244, -71, -7, -3, -1, 63, 243, -1, 47, 242, -5, -1, 241, -1, 31, + 240, -25, -9, -1, 15, -3, -1, 238, 222, -1, 237, 206, -7, -3, -1, + 236, 221, -1, 190, 235, -3, -1, 205, 220, -1, 174, 234, -15, -7, -3, + -1, 189, 219, -1, 204, 158, -3, -1, 233, 173, -1, 218, 188, -7, -3, + -1, 203, 142, -1, 232, 157, -3, -1, 217, 126, -1, 231, 172, 255,-235, +-143, -77, -45, -25, -15, -7, -3, -1, 202, 187, -1, 141, 216, -5, -3, + -1, 14, 224, 13, 230, -5, -3, -1, 110, 156, 201, -1, 94, 186, -9, + -5, -1, 229, -1, 171, 125, -1, 215, 228, -3, -1, 140, 200, -3, -1, + 78, 46, 62, -15, -7, -3, -1, 109, 214, -1, 227, 155, -3, -1, 185, + 170, -1, 226, 30, -7, -3, -1, 225, 93, -1, 213, 124, -3, -1, 199, + 77, -1, 139, 184, -31, -15, -7, -3, -1, 212, 154, -1, 169, 108, -3, + -1, 198, 61, -1, 211, 45, -7, -3, -1, 210, 29, -1, 123, 183, -3, + -1, 209, 92, -1, 197, 138, -17, -7, -3, -1, 168, 153, -1, 76, 196, + -3, -1, 107, 182, -3, -1, 208, 12, 60, -7, -3, -1, 195, 122, -1, + 167, 44, -3, -1, 194, 91, -1, 181, 28, -57, -35, -19, -7, -3, -1, + 137, 152, -1, 193, 75, -5, -3, -1, 192, 11, 59, -3, -1, 176, 10, + 26, -5, -1, 180, -1, 106, 166, -3, -1, 121, 151, -3, -1, 160, 9, + 144, -9, -3, -1, 179, 136, -3, -1, 43, 90, 178, -7, -3, -1, 165, + 27, -1, 177, 105, -1, 150, 164, -17, -9, -5, -3, -1, 74, 120, 135, + -1, 58, 163, -3, -1, 89, 149, -1, 42, 162, -7, -3, -1, 161, 104, + -1, 134, 119, -3, -1, 73, 148, -1, 57, 147, -63, -31, -15, -7, -3, + -1, 88, 133, -1, 41, 103, -3, -1, 118, 146, -1, 25, 145, -7, -3, + -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 40, -17, -7, + -3, -1, 130, 24, -1, 71, 116, -5, -1, 129, -1, 8, 128, -1, 86, + 101, -7, -5, -1, 23, -1, 7, 112, 115, -3, -1, 55, 39, 114, -15, + -7, -3, -1, 70, 100, -1, 85, 113, -3, -1, 54, 99, -1, 69, 84, + -7, -3, -1, 38, 98, -1, 22, 97, -5, -3, -1, 6, 96, 53, -1, + 83, 68, -51, -37, -23, -15, -9, -3, -1, 37, 82, -1, 21, -1, 5, + 80, -1, 81, -1, 52, 67, -3, -1, 36, 66, -1, 51, 20, -9, -5, + -1, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -7, -5, -3, -1, + 3, 48, 34, 18, -1, 33, -1, 2, 32, -3, -1, 17, 1, -1, 16, + 0 +}; + +static short mpeg3_tab_c0[] = +{ + -29, -21, -13, -7, -3, -1, 11, 15, -1, 13, 14, -3, -1, 7, 5, + 9, -3, -1, 6, 3, -1, 10, 12, -3, -1, 2, 1, -1, 4, 8, + 0 +}; + +static short mpeg3_tab_c1[] = +{ + -15, -7, -3, -1, 15, 14, -1, 13, 12, -3, -1, 11, 10, -1, 9, + 8, -7, -3, -1, 7, 6, -1, 5, 4, -3, -1, 3, 2, -1, 1, + 0 +}; + + + +static struct newhuff mpeg3_ht[] = +{ + { /* 0 */ 0 , mpeg3_tab0 } , + { /* 2 */ 0 , mpeg3_tab1 } , + { /* 3 */ 0 , mpeg3_tab2 } , + { /* 3 */ 0 , mpeg3_tab3 } , + { /* 0 */ 0 , mpeg3_tab0 } , + { /* 4 */ 0 , mpeg3_tab5 } , + { /* 4 */ 0 , mpeg3_tab6 } , + { /* 6 */ 0 , mpeg3_tab7 } , + { /* 6 */ 0 , mpeg3_tab8 } , + { /* 6 */ 0 , mpeg3_tab9 } , + { /* 8 */ 0 , mpeg3_tab10 } , + { /* 8 */ 0 , mpeg3_tab11 } , + { /* 8 */ 0 , mpeg3_tab12 } , + { /* 16 */ 0 , mpeg3_tab13 } , + { /* 0 */ 0 , mpeg3_tab0 } , + { /* 16 */ 0 , mpeg3_tab15 } , + + { /* 16 */ 1 , mpeg3_tab16 } , + { /* 16 */ 2 , mpeg3_tab16 } , + { /* 16 */ 3 , mpeg3_tab16 } , + { /* 16 */ 4 , mpeg3_tab16 } , + { /* 16 */ 6 , mpeg3_tab16 } , + { /* 16 */ 8 , mpeg3_tab16 } , + { /* 16 */ 10, mpeg3_tab16 } , + { /* 16 */ 13, mpeg3_tab16 } , + { /* 16 */ 4 , mpeg3_tab24 } , + { /* 16 */ 5 , mpeg3_tab24 } , + { /* 16 */ 6 , mpeg3_tab24 } , + { /* 16 */ 7 , mpeg3_tab24 } , + { /* 16 */ 8 , mpeg3_tab24 } , + { /* 16 */ 9 , mpeg3_tab24 } , + { /* 16 */ 11, mpeg3_tab24 } , + { /* 16 */ 13, mpeg3_tab24 } +}; + +static struct newhuff mpeg3_htc[] = +{ + { /* 1 , 1 , */ 0 , mpeg3_tab_c0 } , + { /* 1 , 1 , */ 0 , mpeg3_tab_c1 } +}; + + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/audio/layer1.c b/core/multimedia/opieplayer/libmpeg3/audio/layer1.c new file mode 100644 index 0000000..0c355f3 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/layer1.c @@ -0,0 +1,6 @@ +#include "mpeg3audio.h" + +int mpeg3audio_dolayer1(mpeg3audio_t *audio) +{ + ; +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/layer2.c b/core/multimedia/opieplayer/libmpeg3/audio/layer2.c new file mode 100644 index 0000000..01582fe --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/layer2.c @@ -0,0 +1,418 @@ +/* + * most other tables are calculated on program start (which is (of course) + * not ISO-conform) .. + * Layer-3 huffman table is in huffman.h + */ + +#include "mpeg3audio.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "tables.h" + +struct al_table alloc_0[] = { + {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, + {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, + {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, + {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, + {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, + {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {2,0},{5,3},{7,5},{16,-32767}, + {2,0},{5,3},{7,5},{16,-32767}, + {2,0},{5,3},{7,5},{16,-32767}, + {2,0},{5,3},{7,5},{16,-32767} }; + +struct al_table alloc_1[] = { + {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, + {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, + {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, + {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, + {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, + {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, + {2,0},{5,3},{7,5},{16,-32767}, + {2,0},{5,3},{7,5},{16,-32767}, + {2,0},{5,3},{7,5},{16,-32767}, + {2,0},{5,3},{7,5},{16,-32767}, + {2,0},{5,3},{7,5},{16,-32767}, + {2,0},{5,3},{7,5},{16,-32767}, + {2,0},{5,3},{7,5},{16,-32767} }; + +struct al_table alloc_2[] = { + {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, + {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, + {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, + {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} }; + +struct al_table alloc_3[] = { + {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, + {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, + {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, + {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} }; + +struct al_table alloc_4[] = { + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, + {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, + {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9}, + {2,0},{5,3},{7,5},{10,9} }; + + +int mpeg3audio_II_select_table(mpeg3audio_t *audio) +{ + static int translate[3][2][16] = + {{{ 0,2,2,2,2,2,2,0,0,0,1,1,1,1,1,0}, + { 0,2,2,0,0,0,1,1,1,1,1,1,1,1,1,0}}, + {{ 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0}, + { 0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0}}, + {{ 0,3,3,3,3,3,3,0,0,0,1,1,1,1,1,0}, + { 0,3,3,0,0,0,1,1,1,1,1,1,1,1,1,0}}}; + int table, sblim; + static struct al_table *tables[5] = + {alloc_0, alloc_1, alloc_2, alloc_3, alloc_4}; + static int sblims[5] = {27, 30, 8, 12, 30}; + + if(audio->lsf) + table = 4; + else + table = translate[audio->sampling_frequency_code][2 - audio->channels][audio->bitrate_index]; + sblim = sblims[table]; + + audio->alloc = tables[table]; + audio->II_sblimit = sblim; + return 0; +} + +int mpeg3audio_II_step_one(mpeg3audio_t *audio, unsigned int *bit_alloc, int *scale) +{ + int stereo = audio->channels - 1; + int sblimit = audio->II_sblimit; + int jsbound = audio->jsbound; + int sblimit2 = audio->II_sblimit << stereo; + struct al_table *alloc1 = audio->alloc; + int i, result = 0; + unsigned int *scfsi_buf = audio->layer2_scfsi_buf; + unsigned int *scfsi, *bita; + int sc, step; + + bita = bit_alloc; + if(stereo) + { +/* Stereo */ + for(i = jsbound;i ; i--, alloc1 += (1 << step)) + { + *bita++ = (char)mpeg3bits_getbits(audio->astream, step = alloc1->bits); + *bita++ = (char)mpeg3bits_getbits(audio->astream, step); + } + for(i = sblimit-jsbound; i; i--, alloc1 += (1 << step)) + { + bita[0] = (char)mpeg3bits_getbits(audio->astream, step = alloc1->bits); + bita[1] = bita[0]; + bita += 2; + } + bita = bit_alloc; + scfsi = scfsi_buf; + for(i = sblimit2; i; i--) + if(*bita++) *scfsi++ = (char)mpeg3bits_getbits(audio->astream, 2); + } + else + { +/* mono */ + for(i = sblimit; i; i--, alloc1 += (1 << step)) + *bita++ = (char)mpeg3bits_getbits(audio->astream, step = alloc1->bits); + bita = bit_alloc; + scfsi = scfsi_buf; + for(i = sblimit; i; i--) if (*bita++) *scfsi++ = (char)mpeg3bits_getbits(audio->astream, 2); + } + + bita = bit_alloc; + scfsi = scfsi_buf; + for(i = sblimit2; i; i--) + { + if(*bita++) + switch(*scfsi++) + { + case 0: + *scale++ = mpeg3bits_getbits(audio->astream, 6); + *scale++ = mpeg3bits_getbits(audio->astream, 6); + *scale++ = mpeg3bits_getbits(audio->astream, 6); + break; + case 1 : + *scale++ = sc = mpeg3bits_getbits(audio->astream, 6); + *scale++ = sc; + *scale++ = mpeg3bits_getbits(audio->astream, 6); + break; + case 2: + *scale++ = sc = mpeg3bits_getbits(audio->astream, 6); + *scale++ = sc; + *scale++ = sc; + break; + default: /* case 3 */ + *scale++ = mpeg3bits_getbits(audio->astream, 6); + *scale++ = sc = mpeg3bits_getbits(audio->astream, 6); + *scale++ = sc; + break; + } + } + return result | mpeg3bits_error(audio->astream); +} + +int mpeg3audio_II_step_two(mpeg3audio_t *audio, unsigned int *bit_alloc, mpeg3_real_t fraction[2][4][SBLIMIT], int *scale, int x1) +{ + int i, j, k, ba, result = 0; + int channels = audio->channels; + int sblimit = audio->II_sblimit; + int jsbound = audio->jsbound; + struct al_table *alloc2, *alloc1 = audio->alloc; + unsigned int *bita = bit_alloc; + int d1, step, test; + + for(i = 0; i < jsbound; i++, alloc1 += (1 << step)) + { + step = alloc1->bits; + for(j = 0; j < channels; j++) + { + if(ba = *bita++) + { + k = (alloc2 = alloc1 + ba)->bits; + if((d1 = alloc2->d) < 0) + { + mpeg3_real_t cm = mpeg3_muls[k][scale[x1]]; + + fraction[j][0][i] = ((mpeg3_real_t)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; + fraction[j][1][i] = ((mpeg3_real_t)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; + fraction[j][2][i] = ((mpeg3_real_t)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; + } + else + { + static int *table[] = + {0, 0, 0, mpeg3_grp_3tab, 0, mpeg3_grp_5tab, 0, 0, 0, mpeg3_grp_9tab}; + unsigned int idx, *tab, m = scale[x1]; + + idx = (unsigned int)mpeg3bits_getbits(audio->astream, k); + tab = (unsigned int*)(table[d1] + idx + idx + idx); + fraction[j][0][i] = mpeg3_muls[*tab++][m]; + fraction[j][1][i] = mpeg3_muls[*tab++][m]; + fraction[j][2][i] = mpeg3_muls[*tab][m]; + } + scale += 3; + } + else + fraction[j][0][i] = fraction[j][1][i] = fraction[j][2][i] = 0.0; + } + } + + for(i = jsbound; i < sblimit; i++, alloc1 += (1 << step)) + { + step = alloc1->bits; +/* channel 1 and channel 2 bitalloc are the same */ + bita++; + if((ba = *bita++)) + { + k=(alloc2 = alloc1+ba)->bits; + if((d1 = alloc2->d) < 0) + { + mpeg3_real_t cm; + + cm = mpeg3_muls[k][scale[x1 + 3]]; + fraction[1][0][i] = (fraction[0][0][i] = (mpeg3_real_t)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; + fraction[1][1][i] = (fraction[0][1][i] = (mpeg3_real_t)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; + fraction[1][2][i] = (fraction[0][2][i] = (mpeg3_real_t)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; + cm = mpeg3_muls[k][scale[x1]]; + fraction[0][0][i] *= cm; + fraction[0][1][i] *= cm; + fraction[0][2][i] *= cm; + } + else + { + static int *table[] = {0, 0, 0, mpeg3_grp_3tab, 0, mpeg3_grp_5tab, 0, 0, 0, mpeg3_grp_9tab}; + unsigned int idx, *tab, m1, m2; + + m1 = scale[x1]; + m2 = scale[x1+3]; + idx = (unsigned int)mpeg3bits_getbits(audio->astream, k); + tab = (unsigned int*)(table[d1] + idx + idx + idx); + fraction[0][0][i] = mpeg3_muls[*tab][m1]; + fraction[1][0][i] = mpeg3_muls[*tab++][m2]; + fraction[0][1][i] = mpeg3_muls[*tab][m1]; + fraction[1][1][i] = mpeg3_muls[*tab++][m2]; + fraction[0][2][i] = mpeg3_muls[*tab][m1]; + fraction[1][2][i] = mpeg3_muls[*tab][m2]; + } + scale += 6; + } + else + { + fraction[0][0][i] = fraction[0][1][i] = fraction[0][2][i] = + fraction[1][0][i] = fraction[1][1][i] = fraction[1][2][i] = 0.0; + } +/* + should we use individual scalefac for channel 2 or + is the current way the right one , where we just copy channel 1 to + channel 2 ?? + The current 'strange' thing is, that we throw away the scalefac + values for the second channel ...!! +-> changed .. now we use the scalefac values of channel one !! +*/ + } + + if(sblimit > SBLIMIT) sblimit = SBLIMIT; + + for(i = sblimit; i < SBLIMIT; i++) + for(j = 0; j < channels; j++) + fraction[j][0][i] = fraction[j][1][i] = fraction[j][2][i] = 0.0; + + return result | mpeg3bits_error(audio->astream); +} + +int mpeg3audio_dolayer2(mpeg3audio_t *audio) +{ + int i, j, result = 0; + int channels = audio->channels; + mpeg3_real_t fraction[2][4][SBLIMIT]; /* pick_table clears unused subbands */ + unsigned int bit_alloc[64]; + int scale[192]; + int single = audio->single; + + if(audio->error_protection) + mpeg3bits_getbits(audio->astream, 16); + + mpeg3audio_II_select_table(audio); + + audio->jsbound = (audio->mode == MPG_MD_JOINT_STEREO) ? + (audio->mode_ext << 2) + 4 : audio->II_sblimit; + + if(channels == 1 || single == 3) + single = 0; + + result |= mpeg3audio_II_step_one(audio, bit_alloc, scale); + + for(i = 0; i < SCALE_BLOCK && !result; i++) + { + result |= mpeg3audio_II_step_two(audio, bit_alloc, fraction, scale, i >> 2); + + for(j = 0; j < 3; j++) + { + if(single >= 0) + { +/* Monaural */ + mpeg3audio_synth_mono(audio, fraction[single][j], audio->pcm_sample, &(audio->pcm_point)); + } + else + { +/* Stereo */ + int p1 = audio->pcm_point; + mpeg3audio_synth_stereo(audio, fraction[0][j], 0, audio->pcm_sample, &p1); + mpeg3audio_synth_stereo(audio, fraction[1][j], 1, audio->pcm_sample, &(audio->pcm_point)); + } + + if(audio->pcm_point / audio->channels >= audio->pcm_allocated - MPEG3AUDIO_PADDING * audio->channels) + { +/* Need more room */ + mpeg3audio_replace_buffer(audio, audio->pcm_allocated + MPEG3AUDIO_PADDING * audio->channels); + } + } + } + + + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/layer3.c b/core/multimedia/opieplayer/libmpeg3/audio/layer3.c new file mode 100644 index 0000000..b8a5f06 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/layer3.c @@ -0,0 +1,1254 @@ +#include "huffman.h" +#include "mpeg3audio.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "tables.h" + +#include +#include + +struct gr_info_s { + int scfsi; + unsigned part2_3_length; + unsigned big_values; + unsigned scalefac_compress; + unsigned block_type; + unsigned mixed_block_flag; + unsigned table_select[3]; + unsigned subblock_gain[3]; + unsigned maxband[3]; + unsigned maxbandl; + unsigned maxb; + unsigned region1start; + unsigned region2start; + unsigned preflag; + unsigned scalefac_scale; + unsigned count1table_select; + mpeg3_real_t *full_gain[3]; + mpeg3_real_t *pow2gain; +}; + +struct mpeg3_III_sideinfo +{ + unsigned main_data_begin; + unsigned private_bits; + struct + { + struct gr_info_s gr[2]; + } ch[2]; +}; + +int mpeg3audio_III_get_scale_factors_1(mpeg3audio_t *audio, + int *scf, + struct gr_info_s *gr_info, + int ch, + int gr) +{ + static unsigned char slen[2][16] = + {{0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4}, + {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3}}; + int numbits; + int num0 = slen[0][gr_info->scalefac_compress]; + int num1 = slen[1][gr_info->scalefac_compress]; + + if (gr_info->block_type == 2) + { + int i = 18; + numbits = (num0 + num1) * 18; + + if (gr_info->mixed_block_flag) + { + for(i = 8; i; i--) + *scf++ = mpeg3bits_getbits(audio->astream, num0); + i = 9; +/* num0 * 17 + num1 * 18 */ + numbits -= num0; + } + + for( ; i; i--) + *scf++ = mpeg3bits_getbits(audio->astream, num0); + for(i = 18; i; i--) + *scf++ = mpeg3bits_getbits(audio->astream, num1); +/* short[13][0..2] = 0 */ + *scf++ = 0; + *scf++ = 0; + *scf++ = 0; + } + else + { + int i; + int scfsi = gr_info->scfsi; + + if(scfsi < 0) + { +/* scfsi < 0 => granule == 0 */ + for(i = 11; i; i--) + { + *scf++ = mpeg3bits_getbits(audio->astream, num0); + } + for(i = 10; i; i--) + *scf++ = mpeg3bits_getbits(audio->astream, num1); + numbits = (num0 + num1) * 10 + num0; + *scf++ = 0; + } + else + { + numbits = 0; + if(!(scfsi & 0x8)) + { + for(i = 0; i < 6; i++) + { + *scf++ = mpeg3bits_getbits(audio->astream, num0); + } + numbits += num0 * 6; + } + else + { + scf += 6; + } + + if(!(scfsi & 0x4)) + { + for(i = 0; i < 5; i++) + *scf++ = mpeg3bits_getbits(audio->astream, num0); + numbits += num0 * 5; + } + else + { + scf += 5; + } + + if(!(scfsi & 0x2)) + { + for(i = 0; i < 5; i++) + *scf++ = mpeg3bits_getbits(audio->astream, num1); + numbits += num1 * 5; + } + else + { + scf += 5; + } + + if(!(scfsi & 0x1)) + { + for(i = 0; i < 5; i++) + *scf++ = mpeg3bits_getbits(audio->astream, num1); + numbits += num1 * 5; + } + else + { + scf += 5; + } + *scf++ = 0; /* no l[21] in original sources */ + } + } + return numbits; +} + +int mpeg3audio_III_get_scale_factors_2(mpeg3audio_t *audio, + int *scf, + struct gr_info_s *gr_info, + int i_stereo) +{ + unsigned char *pnt; + int i, j, n = 0, numbits = 0; + unsigned int slen; + static unsigned char stab[3][6][4] = + {{{ 6, 5, 5,5 }, { 6, 5, 7,3 }, { 11,10,0,0}, + { 7, 7, 7,0 }, { 6, 6, 6,3 }, { 8, 8,5,0}}, + {{ 9, 9, 9,9 }, { 9, 9,12,6 }, { 18,18,0,0}, + {12,12,12,0 }, {12, 9, 9,6 }, { 15,12,9,0}}, + {{ 6, 9, 9,9 }, { 6, 9,12,6 }, { 15,18,0,0}, + { 6,15,12,0 }, { 6,12, 9,6 }, { 6,18,9,0}}}; + +/* i_stereo AND second channel -> do_layer3() checks this */ + if(i_stereo) + slen = mpeg3_i_slen2[gr_info->scalefac_compress >> 1]; + else + slen = mpeg3_n_slen2[gr_info->scalefac_compress]; + + gr_info->preflag = (slen >> 15) & 0x1; + + n = 0; + if(gr_info->block_type == 2 ) + { + n++; + if(gr_info->mixed_block_flag) + n++; + } + + pnt = stab[n][(slen >> 12) & 0x7]; + + for(i = 0; i < 4; i++) + { + int num = slen & 0x7; + slen >>= 3; + if(num) + { + for(j = 0; j < (int)(pnt[i]); j++) + *scf++ = mpeg3bits_getbits(audio->astream, num); + numbits += pnt[i] * num; + } + else + { + for(j = 0; j < (int)(pnt[i]); j++) + *scf++ = 0; + } + } + + n = (n << 1) + 1; + for(i = 0; i < n; i++) + *scf++ = 0; + + return numbits; +} + +static int pretab1[22] = {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0}; +static int pretab2[22] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +/* + * Dequantize samples (includes huffman decoding) + * + * 24 is enough because tab13 has max. a 19 bit huffvector + */ + +#define BITSHIFT ((sizeof(long) - 1) * 8) +#define REFRESH_MASK \ + while(num < BITSHIFT) \ + { \ + mask |= mpeg3bits_getbits(audio->astream, 8) << (BITSHIFT - num); \ + num += 8; \ + part2remain -= 8; \ + } + +int mpeg3audio_III_dequantize_sample(mpeg3audio_t *audio, + mpeg3_real_t xr[SBLIMIT][SSLIMIT], + int *scf, + struct gr_info_s *gr_info, + int sfreq, + int part2bits) +{ + int shift = 1 + gr_info->scalefac_scale; + mpeg3_real_t *xrpnt = (mpeg3_real_t*)xr; + int l[3],l3; + int part2remain = gr_info->part2_3_length - part2bits; + int *me; + int num = mpeg3bits_getbitoffset(audio->astream); + long mask = mpeg3bits_getbits(audio->astream, num); +//printf("III_dequantize_sample 1 %08x %d\n", mask, num); + mask = mask << (BITSHIFT + 8 - num); + part2remain -= num; + + { + int bv = gr_info->big_values; + int region1 = gr_info->region1start; + int region2 = gr_info->region2start; + + l3 = ((576 >> 1) - bv) >> 1; + +/* + * we may lose the 'odd' bit here !! + * check this later again + */ + + if(bv <= region1) + { + l[0] = bv; + l[1] = 0; + l[2] = 0; + } + else + { + l[0] = region1; + if(bv <= region2) + { + l[1] = bv - l[0]; l[2] = 0; + } + else + { + l[1] = region2 - l[0]; + l[2] = bv - region2; + } + } + } + + if(gr_info->block_type == 2) + { +/* + * decoding with short or mixed mode BandIndex table + */ + int i, max[4]; + int step = 0, lwin = 3, cb = 0; + register mpeg3_real_t v = 0.0; + register int *m, mc; + + if(gr_info->mixed_block_flag) + { + max[3] = -1; + max[0] = max[1] = max[2] = 2; + m = mpeg3_map[sfreq][0]; + me = mpeg3_mapend[sfreq][0]; + } + else + { + max[0] = max[1] = max[2] = max[3] = -1; +/* max[3] not floatly needed in this case */ + m = mpeg3_map[sfreq][1]; + me = mpeg3_mapend[sfreq][1]; + } + + mc = 0; + for(i = 0; i < 2; i++) + { + int lp = l[i]; + struct newhuff *h = mpeg3_ht + gr_info->table_select[i]; + for( ; lp; lp--, mc--) + { + register int x,y; + if(!mc) + { + mc = *m++; + xrpnt = ((mpeg3_real_t*)xr) + (*m++); + lwin = *m++; + cb = *m++; + if(lwin == 3) + { + v = gr_info->pow2gain[(*scf++) << shift]; + step = 1; + } + else + { + v = gr_info->full_gain[lwin][(*scf++) << shift]; + step = 3; + } + } + + { + register short *val = h->table; + REFRESH_MASK; + while((y = *val++) < 0) + { + if (mask < 0) + val -= y; + num--; + mask <<= 1; + } + x = y >> 4; + y &= 0xf; + } + + if(x == 15 && h->linbits) + { + max[lwin] = cb; + REFRESH_MASK; + x += ((unsigned long)mask) >> (BITSHIFT + 8 - h->linbits); + num -= h->linbits + 1; + mask <<= h->linbits; + if(mask < 0) + *xrpnt = -mpeg3_ispow[x] * v; + else + *xrpnt = mpeg3_ispow[x] * v; + mask <<= 1; + } + else + if(x) + { + max[lwin] = cb; + if(mask < 0) + *xrpnt = -mpeg3_ispow[x] * v; + else + *xrpnt = mpeg3_ispow[x] * v; + num--; + mask <<= 1; + } + else + *xrpnt = 0.0; + + xrpnt += step; + if(y == 15 && h->linbits) + { + max[lwin] = cb; + REFRESH_MASK; + y += ((unsigned long) mask) >> (BITSHIFT + 8 - h->linbits); + num -= h->linbits + 1; + mask <<= h->linbits; + if(mask < 0) + *xrpnt = -mpeg3_ispow[y] * v; + else + *xrpnt = mpeg3_ispow[y] * v; + mask <<= 1; + } + else + if(y) + { + max[lwin] = cb; + if(mask < 0) + *xrpnt = -mpeg3_ispow[y] * v; + else + *xrpnt = mpeg3_ispow[y] * v; + num--; + mask <<= 1; + } + else + *xrpnt = 0.0; + xrpnt += step; + } + } + + for( ;l3 && (part2remain + num > 0); l3--) + { + struct newhuff *h = mpeg3_htc + gr_info->count1table_select; + register short *val = h->table, a; + + REFRESH_MASK; + while((a = *val++) < 0) + { + if (mask < 0) + val -= a; + num--; + mask <<= 1; + } + if(part2remain + num <= 0) + { + num -= part2remain + num; + break; + } + + for(i = 0; i < 4; i++) + { + if(!(i & 1)) + { + if(!mc) + { + mc = *m++; + xrpnt = ((mpeg3_real_t*)xr) + (*m++); + lwin = *m++; + cb = *m++; + if(lwin == 3) + { + v = gr_info->pow2gain[(*scf++) << shift]; + step = 1; + } + else + { + v = gr_info->full_gain[lwin][(*scf++) << shift]; + step = 3; + } + } + mc--; + } + if((a & (0x8 >> i))) + { + max[lwin] = cb; + if(part2remain + num <= 0) + { + break; + } + if(mask < 0) + *xrpnt = -v; + else + *xrpnt = v; + num--; + mask <<= 1; + } + else + *xrpnt = 0.0; + xrpnt += step; + } + } + + if(lwin < 3) + { +/* short band? */ + while(1) + { + for( ;mc > 0; mc--) + { +/* short band -> step=3 */ + *xrpnt = 0.0; + xrpnt += 3; + *xrpnt = 0.0; + xrpnt += 3; + } + if(m >= me) + break; + mc = *m++; + xrpnt = ((mpeg3_real_t*)xr) + *m++; +/* optimize: field will be set to zero at the end of the function */ + if(*m++ == 0) + break; +/* cb */ + m++; + } + } + + gr_info->maxband[0] = max[0] + 1; + gr_info->maxband[1] = max[1] + 1; + gr_info->maxband[2] = max[2] + 1; + gr_info->maxbandl = max[3] + 1; + + { + int rmax = max[0] > max[1] ? max[0] : max[1]; + rmax = (rmax > max[2] ? rmax : max[2]) + 1; + gr_info->maxb = rmax ? mpeg3_shortLimit[sfreq][rmax] : mpeg3_longLimit[sfreq][max[3] + 1]; + } + + } + else + { +/* + * decoding with 'long' BandIndex table (block_type != 2) + */ + int *pretab = gr_info->preflag ? pretab1 : pretab2; + int i, max = -1; + int cb = 0; + int *m = mpeg3_map[sfreq][2]; + register mpeg3_real_t v = 0.0; + int mc = 0; + +/* + * long hash table values + */ + for(i = 0; i < 3; i++) + { + int lp = l[i]; + struct newhuff *h = mpeg3_ht + gr_info->table_select[i]; + + for(; lp; lp--, mc--) + { + int x, y; + + if(!mc) + { + mc = *m++; + cb = *m++; + if(cb == 21) + v = 0.0; + else + v = gr_info->pow2gain[((*scf++) + (*pretab++)) << shift]; + } + { + register short *val = h->table; + REFRESH_MASK; + while((y = *val++) < 0) + { + if(mask < 0) + val -= y; + num--; + mask <<= 1; + } + x = y >> 4; + y &= 0xf; + } + + if(x == 15 && h->linbits) + { + max = cb; + REFRESH_MASK; + x += ((unsigned long) mask) >> (BITSHIFT + 8 - h->linbits); + num -= h->linbits + 1; + mask <<= h->linbits; + if(mask < 0) + *xrpnt++ = -mpeg3_ispow[x] * v; + else + *xrpnt++ = mpeg3_ispow[x] * v; + mask <<= 1; + } + else + if(x) + { + max = cb; + if(mask < 0) + *xrpnt++ = -mpeg3_ispow[x] * v; + else + *xrpnt++ = mpeg3_ispow[x] * v; + num--; + mask <<= 1; + } + else + *xrpnt++ = 0.0; + + if(y == 15 && h->linbits) + { + max = cb; + REFRESH_MASK; + y += ((unsigned long) mask) >> (BITSHIFT + 8 - h->linbits); + num -= h->linbits + 1; + mask <<= h->linbits; + if(mask < 0) + *xrpnt++ = -mpeg3_ispow[y] * v; + else + *xrpnt++ = mpeg3_ispow[y] * v; + mask <<= 1; + } + else + if(y) + { + max = cb; + if(mask < 0) + *xrpnt++ = -mpeg3_ispow[y] * v; + else + *xrpnt++ = mpeg3_ispow[y] * v; + num--; + mask <<= 1; + } + else + *xrpnt++ = 0.0; + } + } + +/* + * short (count1table) values + */ + for( ; l3 && (part2remain + num > 0); l3--) + { + struct newhuff *h = mpeg3_htc + gr_info->count1table_select; + register short *val = h->table, a; + + REFRESH_MASK; + while((a = *val++) < 0) + { + if(mask < 0) + val -= a; + num--; + mask <<= 1; + } + if(part2remain + num <= 0) + { + num -= part2remain + num; + break; + } + + for(i = 0; i < 4; i++) + { + if(!(i & 1)) + { + if(!mc) + { + mc = *m++; + cb = *m++; + if(cb == 21) + v = 0.0; + else + v = gr_info->pow2gain[((*scf++) + (*pretab++)) << shift]; + } + mc--; + } + if((a & (0x8 >> i))) + { + max = cb; + if(part2remain + num <= 0) + { + break; + } + if(mask < 0) + *xrpnt++ = -v; + else + *xrpnt++ = v; + num--; + mask <<= 1; + } + else + *xrpnt++ = 0.0; + } + } + + gr_info->maxbandl = max + 1; + gr_info->maxb = mpeg3_longLimit[sfreq][gr_info->maxbandl]; + } + + part2remain += num; + +//printf("III_dequantize_sample 2 %d %04x\n", num, mpeg3bits_showbits(audio->astream, 16)); + mpeg3bits_start_reverse(audio->astream); + mpeg3bits_getbits_reverse(audio->astream, num); + mpeg3bits_start_forward(audio->astream); +//printf("III_dequantize_sample 3 %d %04x\n", audio->astream->bit_number, mpeg3bits_showbits(audio->astream, 16)); + num = 0; + + while(xrpnt < &xr[SBLIMIT][0]) + *xrpnt++ = 0.0; + + while(part2remain > 16) + { + mpeg3bits_getbits(audio->astream, 16); /* Dismiss stuffing Bits */ + part2remain -= 16; + } + if(part2remain > 0) + { + mpeg3bits_getbits(audio->astream, part2remain); + } + else + if(part2remain < 0) + { + fprintf(stderr,"mpeg3audio_III_dequantize_sample: Can't rewind stream %d bits!\n", -part2remain); + return 1; /* -> error */ + } + return 0; +} + +int mpeg3audio_III_get_side_info(mpeg3audio_t *audio, + struct mpeg3_III_sideinfo *si, + int channels, + int ms_stereo, + long sfreq, + int single, + int lsf) +{ + int ch, gr; + int powdiff = (single == 3) ? 4 : 0; + static const int tabs[2][5] = { { 2,9,5,3,4 } , { 1,8,1,2,9 } }; + const int *tab = tabs[lsf]; + + si->main_data_begin = mpeg3bits_getbits(audio->astream, tab[1]); + if(channels == 1) + si->private_bits = mpeg3bits_getbits(audio->astream, tab[2]); + else + si->private_bits = mpeg3bits_getbits(audio->astream, tab[3]); + if(!lsf) + { + for(ch = 0; ch < channels; ch++) + { + si->ch[ch].gr[0].scfsi = -1; + si->ch[ch].gr[1].scfsi = mpeg3bits_getbits(audio->astream, 4); + } + } + + for(gr = 0; gr < tab[0]; gr++) + { + for(ch = 0; ch < channels; ch++) + { + register struct gr_info_s *gr_info = &(si->ch[ch].gr[gr]); + + gr_info->part2_3_length = mpeg3bits_getbits(audio->astream, 12); + gr_info->big_values = mpeg3bits_getbits(audio->astream, 9); + if(gr_info->big_values > 288) + { + fprintf(stderr,"mpeg3_III_get_side_info: big_values too large!\n"); + gr_info->big_values = 288; + } + gr_info->pow2gain = mpeg3_gainpow2 + 256 - mpeg3bits_getbits(audio->astream, 8) + powdiff; + if(ms_stereo) + gr_info->pow2gain += 2; + gr_info->scalefac_compress = mpeg3bits_getbits(audio->astream, tab[4]); + + if(mpeg3bits_getbits(audio->astream, 1)) + { +/* window switch flag */ + int i; + gr_info->block_type = mpeg3bits_getbits(audio->astream, 2); + gr_info->mixed_block_flag = mpeg3bits_getbits(audio->astream, 1); + gr_info->table_select[0] = mpeg3bits_getbits(audio->astream, 5); + gr_info->table_select[1] = mpeg3bits_getbits(audio->astream, 5); +/* + * table_select[2] not needed, because there is no region2, + * but to satisfy some verifications tools we set it either. + */ + gr_info->table_select[2] = 0; + for(i = 0; i < 3; i++) + gr_info->full_gain[i] = gr_info->pow2gain + (mpeg3bits_getbits(audio->astream, 3) << 3); + + if(gr_info->block_type == 0) + { + fprintf(stderr,"Blocktype == 0 and window-switching == 1 not allowed.\n"); + return 1; + } + +/* region_count/start parameters are implicit in this case. */ + if(!lsf || gr_info->block_type == 2) + gr_info->region1start = 36 >> 1; + else + { +/* check this again for 2.5 and sfreq=8 */ + if(sfreq == 8) + gr_info->region1start = 108 >> 1; + else + gr_info->region1start = 54 >> 1; + } + gr_info->region2start = 576 >> 1; + } + else + { + int i, r0c, r1c; + for(i = 0; i < 3; i++) + gr_info->table_select[i] = mpeg3bits_getbits(audio->astream, 5); + + r0c = mpeg3bits_getbits(audio->astream, 4); + r1c = mpeg3bits_getbits(audio->astream, 3); + gr_info->region1start = mpeg3_bandInfo[sfreq].longIdx[r0c + 1] >> 1 ; + gr_info->region2start = mpeg3_bandInfo[sfreq].longIdx[r0c + 1 + r1c + 1] >> 1; + gr_info->block_type = 0; + gr_info->mixed_block_flag = 0; + } + if(!lsf) gr_info->preflag = mpeg3bits_getbits(audio->astream, 1); + gr_info->scalefac_scale = mpeg3bits_getbits(audio->astream, 1); + gr_info->count1table_select = mpeg3bits_getbits(audio->astream, 1); + } + } + return 0; +} + +int mpeg3audio_III_hybrid(mpeg3audio_t *audio, + mpeg3_real_t fsIn[SBLIMIT][SSLIMIT], + mpeg3_real_t tsOut[SSLIMIT][SBLIMIT], + int ch, + struct gr_info_s *gr_info) +{ + mpeg3_real_t *tspnt = (mpeg3_real_t *) tsOut; + mpeg3_real_t *rawout1,*rawout2; + int bt, sb = 0; + + + { + int b = audio->mp3_blc[ch]; + rawout1 = audio->mp3_block[b][ch]; + b = -b + 1; + rawout2 = audio->mp3_block[b][ch]; + audio->mp3_blc[ch] = b; + } + + if(gr_info->mixed_block_flag) + { + sb = 2; + mpeg3audio_dct36(fsIn[0], rawout1, rawout2, mpeg3_win[0], tspnt); + mpeg3audio_dct36(fsIn[1], rawout1 + 18, rawout2 + 18, mpeg3_win1[0], tspnt + 1); + rawout1 += 36; + rawout2 += 36; + tspnt += 2; + } + + bt = gr_info->block_type; + if(bt == 2) + { + for( ; sb < gr_info->maxb; sb += 2, tspnt += 2, rawout1 += 36, rawout2 += 36) + { + mpeg3audio_dct12(fsIn[sb] ,rawout1 ,rawout2 ,mpeg3_win[2] ,tspnt); + mpeg3audio_dct12(fsIn[sb + 1], rawout1 + 18, rawout2 + 18, mpeg3_win1[2], tspnt + 1); + } + } + else + { + for( ; sb < gr_info->maxb; sb += 2, tspnt += 2, rawout1 += 36, rawout2 += 36) + { + mpeg3audio_dct36(fsIn[sb], rawout1, rawout2, mpeg3_win[bt], tspnt); + mpeg3audio_dct36(fsIn[sb + 1], rawout1 + 18, rawout2 + 18, mpeg3_win1[bt], tspnt + 1); + } + } + + for( ; sb < SBLIMIT; sb++, tspnt++) + { + int i; + for(i = 0; i < SSLIMIT; i++) + { + tspnt[i * SBLIMIT] = *rawout1++; + *rawout2++ = 0.0; + } + } + return 0; +} + +int mpeg3audio_III_antialias(mpeg3audio_t *audio, + mpeg3_real_t xr[SBLIMIT][SSLIMIT], + struct gr_info_s *gr_info) +{ + int sblim; + + if(gr_info->block_type == 2) + { + if(!gr_info->mixed_block_flag) + return 0; + sblim = 1; + } + else + { + sblim = gr_info->maxb-1; + } + +/* 31 alias-reduction operations between each pair of sub-bands */ +/* with 8 butterflies between each pair */ + + { + int sb; + mpeg3_real_t *xr1 = (mpeg3_real_t*)xr[1]; + + for(sb = sblim; sb; sb--, xr1 += 10) + { + int ss; + mpeg3_real_t *cs, *ca; + mpeg3_real_t *xr2; + cs = mpeg3_aa_cs; + ca = mpeg3_aa_ca; + xr2 = xr1; + + for(ss = 7; ss >= 0; ss--) + { +/* upper and lower butterfly inputs */ + register mpeg3_real_t bu, bd; + bu = *--xr2; + bd = *xr1; + *xr2 = (bu * (*cs) ) - (bd * (*ca) ); + *xr1++ = (bd * (*cs++) ) + (bu * (*ca++) ); + } + } + } + return 0; +} + +/* + * III_stereo: calculate mpeg3_real_t channel values for Joint-I-Stereo-mode + */ +int mpeg3audio_III_i_stereo(mpeg3audio_t *audio, + mpeg3_real_t xr_buf[2][SBLIMIT][SSLIMIT], + int *scalefac, + struct gr_info_s *gr_info, + int sfreq, + int ms_stereo, + int lsf) +{ + mpeg3_real_t (*xr)[SBLIMIT*SSLIMIT] = (mpeg3_real_t (*)[SBLIMIT*SSLIMIT] ) xr_buf; + struct mpeg3_bandInfoStruct *bi = &mpeg3_bandInfo[sfreq]; + const mpeg3_real_t *tab1, *tab2; + + int tab; +/* TODO: optimize as static */ + static const mpeg3_real_t *tabs[3][2][2] = + { + { { mpeg3_tan1_1, mpeg3_tan2_1 } , { mpeg3_tan1_2, mpeg3_tan2_2 } }, + { { mpeg3_pow1_1[0], mpeg3_pow2_1[0] } , { mpeg3_pow1_2[0], mpeg3_pow2_2[0] } } , + { { mpeg3_pow1_1[1], mpeg3_pow2_1[1] } , { mpeg3_pow1_2[1], mpeg3_pow2_2[1] } } + }; + + tab = lsf + (gr_info->scalefac_compress & lsf); + tab1 = tabs[tab][ms_stereo][0]; + tab2 = tabs[tab][ms_stereo][1]; + + if(gr_info->block_type == 2) + { + int lwin,do_l = 0; + if(gr_info->mixed_block_flag) + do_l = 1; + + for(lwin = 0; lwin < 3; lwin++) + { +/* process each window */ +/* get first band with zero values */ +/* sfb is minimal 3 for mixed mode */ + int is_p, sb, idx, sfb = gr_info->maxband[lwin]; + if(sfb > 3) do_l = 0; + + for( ; sfb < 12 ; sfb++) + { +/* scale: 0-15 */ + is_p = scalefac[sfb * 3 + lwin - gr_info->mixed_block_flag]; + if(is_p != 7) + { + mpeg3_real_t t1, t2; + sb = bi->shortDiff[sfb]; + idx = bi->shortIdx[sfb] + lwin; + t1 = tab1[is_p]; + t2 = tab2[is_p]; + for( ; sb > 0; sb--, idx += 3) + { + mpeg3_real_t v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + } + +/* in the original: copy 10 to 11 , here: copy 11 to 12 +maybe still wrong??? (copy 12 to 13?) */ +/* scale: 0-15 */ + is_p = scalefac[11 * 3 + lwin - gr_info->mixed_block_flag]; + sb = bi->shortDiff[12]; + idx = bi->shortIdx[12] + lwin; + if(is_p != 7) + { + mpeg3_real_t t1, t2; + t1 = tab1[is_p]; + t2 = tab2[is_p]; + for( ; sb > 0; sb--, idx += 3) + { + mpeg3_real_t v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + } /* end for(lwin; .. ; . ) */ + +/* also check l-part, if ALL bands in the three windows are 'empty' +* and mode = mixed_mode +*/ + if(do_l) + { + int sfb = gr_info->maxbandl; + int idx = bi->longIdx[sfb]; + + for ( ; sfb < 8; sfb++) + { + int sb = bi->longDiff[sfb]; +/* scale: 0-15 */ + int is_p = scalefac[sfb]; + if(is_p != 7) + { + mpeg3_real_t t1, t2; + t1 = tab1[is_p]; + t2 = tab2[is_p]; + for( ; sb > 0; sb--, idx++) + { + mpeg3_real_t v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + else + idx += sb; + } + } + } + else + { +/* ((gr_info->block_type != 2)) */ + int sfb = gr_info->maxbandl; + int is_p, idx = bi->longIdx[sfb]; + for( ; sfb < 21; sfb++) + { + int sb = bi->longDiff[sfb]; +/* scale: 0-15 */ + is_p = scalefac[sfb]; + if(is_p != 7) + { + mpeg3_real_t t1, t2; + t1 = tab1[is_p]; + t2 = tab2[is_p]; + for( ; sb > 0; sb--, idx++) + { + mpeg3_real_t v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + else + idx += sb; + } + + is_p = scalefac[20]; + if(is_p != 7) + { +/* copy l-band 20 to l-band 21 */ + int sb; + mpeg3_real_t t1 = tab1[is_p], t2 = tab2[is_p]; + + for(sb = bi->longDiff[21]; sb > 0; sb--, idx++) + { + mpeg3_real_t v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + } /* ... */ +} + +/* Read just the frame after a seek. */ +int mpeg3audio_read_layer3_frame(mpeg3audio_t *audio) +{ + int result = 0; + + result = mpeg3audio_read_header(audio); + if(!result) + { + audio->bsbufold = audio->bsbuf; + audio->bsbuf = audio->bsspace[audio->bsnum] + 512; + audio->bsnum ^= 1; + result = mpeg3bits_read_buffer(audio->astream, audio->bsbuf, audio->framesize); + } + + return result; +} + +int mpeg3audio_dolayer3(mpeg3audio_t *audio) +{ + int gr, ch, ss; + int scalefacs[2][39]; /* max 39 for short[13][3] mode, mixed: 38, long: 22 */ + struct mpeg3_III_sideinfo sideinfo; + int channels = audio->channels; + int single = audio->single; + int ms_stereo, i_stereo; + int sfreq = audio->sampling_frequency_code; + int stereo1, granules; + int i; + +/* flip/init buffer */ + audio->bsbufold = audio->bsbuf; + audio->bsbuf = audio->bsspace[audio->bsnum] + 512; + audio->bsnum ^= 1; + +/* read main data into memory */ + if(mpeg3bits_read_buffer(audio->astream, audio->bsbuf, audio->framesize)) + return 1; + mpeg3bits_use_ptr(audio->astream, audio->bsbuf); + +/* CRC must be skipped here for proper alignment with the backstep */ + if(audio->error_protection) + mpeg3bits_getbits(audio->astream, 16); + + if(channels == 1) + { +/* stream is mono */ + stereo1 = 1; + single = 0; + } + else + { +/* Stereo */ + stereo1 = 2; + } + + if(audio->mode == MPG_MD_JOINT_STEREO) + { + ms_stereo = (audio->mode_ext & 0x2) >> 1; + i_stereo = audio->mode_ext & 0x1; + } + else + ms_stereo = i_stereo = 0; + + if(audio->lsf) + { + granules = 1; + } + else + { + granules = 2; + } + + if(mpeg3audio_III_get_side_info(audio, &sideinfo, channels, ms_stereo, sfreq, single, audio->lsf)) + return 1; + +/* Step back */ + if(sideinfo.main_data_begin >= 512) + return 1; + + if(sideinfo.main_data_begin) + { + memcpy(audio->bsbuf + audio->ssize - sideinfo.main_data_begin, + audio->bsbufold + audio->prev_framesize - sideinfo.main_data_begin, + sideinfo.main_data_begin); + mpeg3bits_use_ptr(audio->astream, audio->bsbuf + audio->ssize - sideinfo.main_data_begin); + } + + for(gr = 0; gr < granules; gr++) + { + mpeg3_real_t hybridIn [2][SBLIMIT][SSLIMIT]; + mpeg3_real_t hybridOut[2][SSLIMIT][SBLIMIT]; + + { + struct gr_info_s *gr_info = &(sideinfo.ch[0].gr[gr]); + long part2bits; + if(audio->lsf) + part2bits = mpeg3audio_III_get_scale_factors_2(audio, scalefacs[0], gr_info, 0); + else + part2bits = mpeg3audio_III_get_scale_factors_1(audio, scalefacs[0], gr_info, 0, gr); +//printf("dolayer3 4 %04x\n", mpeg3bits_showbits(audio->astream, 16)); + + if(mpeg3audio_III_dequantize_sample(audio, hybridIn[0], scalefacs[0], gr_info, sfreq, part2bits)) + { + mpeg3bits_use_demuxer(audio->astream); + return 1; + } +//printf("dolayer3 5 %04x\n", mpeg3bits_showbits(audio->astream, 16)); + } + + if(channels == 2) + { + struct gr_info_s *gr_info = &(sideinfo.ch[1].gr[gr]); + long part2bits; + if(audio->lsf) + part2bits = mpeg3audio_III_get_scale_factors_2(audio, scalefacs[1], gr_info, i_stereo); + else + part2bits = mpeg3audio_III_get_scale_factors_1(audio, scalefacs[1], gr_info, 1, gr); + + if(mpeg3audio_III_dequantize_sample(audio, hybridIn[1], scalefacs[1], gr_info, sfreq, part2bits)) + { + mpeg3bits_use_demuxer(audio->astream); + return 1; + } + + if(ms_stereo) + { + int i; + int maxb = sideinfo.ch[0].gr[gr].maxb; + if(sideinfo.ch[1].gr[gr].maxb > maxb) + maxb = sideinfo.ch[1].gr[gr].maxb; + for(i = 0; i < SSLIMIT * maxb; i++) + { + mpeg3_real_t tmp0 = ((mpeg3_real_t*)hybridIn[0])[i]; + mpeg3_real_t tmp1 = ((mpeg3_real_t*)hybridIn[1])[i]; + ((mpeg3_real_t*)hybridIn[0])[i] = tmp0 + tmp1; + ((mpeg3_real_t*)hybridIn[1])[i] = tmp0 - tmp1; + } + } + + if(i_stereo) + mpeg3audio_III_i_stereo(audio, hybridIn, scalefacs[1], gr_info, sfreq, ms_stereo, audio->lsf); + + if(ms_stereo || i_stereo || (single == 3)) + { + if(gr_info->maxb > sideinfo.ch[0].gr[gr].maxb) + sideinfo.ch[0].gr[gr].maxb = gr_info->maxb; + else + gr_info->maxb = sideinfo.ch[0].gr[gr].maxb; + } + + switch(single) + { + case 3: + { + register int i; + register mpeg3_real_t *in0 = (mpeg3_real_t*)hybridIn[0], *in1 = (mpeg3_real_t*)hybridIn[1]; +/* *0.5 done by pow-scale */ + for(i = 0; i < SSLIMIT * gr_info->maxb; i++, in0++) + *in0 = (*in0 + *in1++); + } + break; + case 1: + { + register int i; + register mpeg3_real_t *in0 = (mpeg3_real_t*)hybridIn[0], *in1 = (mpeg3_real_t*)hybridIn[1]; + for(i = 0; i < SSLIMIT * gr_info->maxb; i++) + *in0++ = *in1++; + } + break; + } + } + + for(ch = 0; ch < stereo1; ch++) + { + struct gr_info_s *gr_info = &(sideinfo.ch[ch].gr[gr]); + mpeg3audio_III_antialias(audio, hybridIn[ch], gr_info); + mpeg3audio_III_hybrid(audio, hybridIn[ch], hybridOut[ch], ch, gr_info); + } + + for(ss = 0; ss < SSLIMIT; ss++) + { + if(single >= 0) + { + mpeg3audio_synth_mono(audio, hybridOut[0][ss], audio->pcm_sample, &(audio->pcm_point)); + } + else + { + int p1 = audio->pcm_point; + mpeg3audio_synth_stereo(audio, hybridOut[0][ss], 0, audio->pcm_sample, &p1); + mpeg3audio_synth_stereo(audio, hybridOut[1][ss], 1, audio->pcm_sample, &(audio->pcm_point)); + } + + if(audio->pcm_point / audio->channels >= audio->pcm_allocated - MPEG3AUDIO_PADDING * audio->channels) + { +/* Need more room */ + mpeg3audio_replace_buffer(audio, audio->pcm_allocated + MPEG3AUDIO_PADDING * audio->channels); + } + } + } + + mpeg3bits_use_demuxer(audio->astream); + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/mantissa.c b/core/multimedia/opieplayer/libmpeg3/audio/mantissa.c new file mode 100644 index 0000000..05fe251 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/mantissa.c @@ -0,0 +1,387 @@ +/* + * + * mantissa.c Copyright (C) Aaron Holtzman - May 1999 + * + * + * This file is part of libmpeg3 + * + * libmpeg3 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. + * + * libmpeg3 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. + * + */ + +#include "mpeg3audio.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" + + +/* Lookup tables of 0.16 two's complement quantization values */ +static short mpeg3_q_1[3] = +{ + (-2 << 15) / 3, + 0, + (2 << 15) / 3 +}; + +static short mpeg3_q_2[5] = +{ + (-4 << 15) / 5, + ((-2 << 15) / 5) << 1, + 0, + (2 << 15) / 5, + ((4 << 15) / 5) << 1 +}; + +static short mpeg3_q_3[7] = +{ + (-6 << 15) / 7, + (-4 << 15) / 7, + (-2 << 15) / 7, + 0, + (2 << 15) / 7, + (4 << 15) / 7, + (6 << 15) / 7 +}; + +static short mpeg3_q_4[11] = +{ + (-10 << 15) / 11, + (-8 << 15) / 11, + (-6 << 15) / 11, + (-4 << 15) / 11, + (-2 << 15) / 11, + 0, + ( 2 << 15) / 11, + ( 4 << 15) / 11, + ( 6 << 15) / 11, + ( 8 << 15) / 11, + (10 << 15) / 11 +}; + +static short mpeg3_q_5[15] = +{ + (-14 << 15) / 15, + (-12 << 15) / 15, + (-10 << 15) / 15, + (-8 << 15) / 15, + (-6 << 15) / 15, + (-4 << 15) / 15, + (-2 << 15) / 15, + 0, + ( 2 << 15) / 15, + ( 4 << 15) / 15, + ( 6 << 15) / 15, + ( 8 << 15) / 15, + (10 << 15) / 15, + (12 << 15) / 15, + (14 << 15) / 15 +}; + +static short mpeg3_qnttztab[16] = {0, 0, 0, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16}; + + +/* */ +/* Scale factors for tofloat */ +/* */ + +static const unsigned MPEG3_INT32 mpeg3_scale_factors[25] = +{ + 0x38000000, /*2 ^ -(0 + 15) */ + 0x37800000, /*2 ^ -(1 + 15) */ + 0x37000000, /*2 ^ -(2 + 15) */ + 0x36800000, /*2 ^ -(3 + 15) */ + 0x36000000, /*2 ^ -(4 + 15) */ + 0x35800000, /*2 ^ -(5 + 15) */ + 0x35000000, /*2 ^ -(6 + 15) */ + 0x34800000, /*2 ^ -(7 + 15) */ + 0x34000000, /*2 ^ -(8 + 15) */ + 0x33800000, /*2 ^ -(9 + 15) */ + 0x33000000, /*2 ^ -(10 + 15) */ + 0x32800000, /*2 ^ -(11 + 15) */ + 0x32000000, /*2 ^ -(12 + 15) */ + 0x31800000, /*2 ^ -(13 + 15) */ + 0x31000000, /*2 ^ -(14 + 15) */ + 0x30800000, /*2 ^ -(15 + 15) */ + 0x30000000, /*2 ^ -(16 + 15) */ + 0x2f800000, /*2 ^ -(17 + 15) */ + 0x2f000000, /*2 ^ -(18 + 15) */ + 0x2e800000, /*2 ^ -(19 + 15) */ + 0x2e000000, /*2 ^ -(20 + 15) */ + 0x2d800000, /*2 ^ -(21 + 15) */ + 0x2d000000, /*2 ^ -(22 + 15) */ + 0x2c800000, /*2 ^ -(23 + 15) */ + 0x2c000000 /*2 ^ -(24 + 15) */ +}; + +static MPEG3_FLOAT32 *mpeg3_scale_factor = (MPEG3_FLOAT32*)mpeg3_scale_factors; + +static inline mpeg3_real_t mpeg3audio_ac3_tofloat(unsigned short exponent, int mantissa) +{ + mpeg3_real_t x; + x = mantissa * mpeg3_scale_factor[exponent]; + return x; +} + +static inline void mpeg3audio_ac3_mantissa_reset(mpeg3_ac3_mantissa_t *mantissa) +{ + mantissa->m_1[2] = mantissa->m_1[1] = mantissa->m_1[0] = 0; + mantissa->m_2[2] = mantissa->m_2[1] = mantissa->m_2[0] = 0; + mantissa->m_4[1] = mantissa->m_4[0] = 0; +/* Force new groups to be loaded */ + mantissa->m_1_pointer = mantissa->m_2_pointer = mantissa->m_4_pointer = 3; +} + +/* + * Generate eight bits of pseudo-entropy using a 16 bit linear + * feedback shift register (LFSR). The primitive polynomial used + * is 1 + x^4 + x^14 + x^16. + * + * The distribution is uniform, over the range [-0.707,0.707] + * + */ +inline unsigned int mpeg3audio_ac3_dither_gen(mpeg3audio_t *audio) +{ + int i; + unsigned int state; + +/* explicitly bring the state into a local var as gcc > 3.0? */ +/* doesn't know how to optimize out the stores */ + state = audio->ac3_lfsr_state; + +/* Generate eight pseudo random bits */ + for(i = 0; i < 8; i++) + { + state <<= 1; + + if(state & 0x10000) + state ^= 0xa011; + } + + audio->ac3_lfsr_state = state; + return (((((int)state << 8) >> 8) * (int)(0.707106f * 256.0f)) >> 16); +} + + +/* Fetch an unpacked, left justified, and properly biased/dithered mantissa value */ +static inline unsigned short mpeg3audio_ac3_mantissa_get(mpeg3audio_t *audio, + unsigned short bap, + unsigned short dithflag) +{ + unsigned short mantissa; + unsigned int group_code; + mpeg3_ac3_mantissa_t *mantissa_struct = &(audio->ac3_mantissa); + +/* If the bap is 0-5 then we have special cases to take care of */ + switch(bap) + { + case 0: + if(dithflag) + mantissa = mpeg3audio_ac3_dither_gen(audio); + else + mantissa = 0; + break; + + case 1: + if(mantissa_struct->m_1_pointer > 2) + { + group_code = mpeg3bits_getbits(audio->astream, 5); + + if(group_code > 26) + { +/* FIXME do proper block error handling */ + fprintf(stderr, "mpeg3audio_ac3_mantissa_get: Invalid mantissa 1 %d\n", group_code); + return 0; + } + + mantissa_struct->m_1[0] = group_code / 9; + mantissa_struct->m_1[1] = (group_code % 9) / 3; + mantissa_struct->m_1[2] = (group_code % 9) % 3; + mantissa_struct->m_1_pointer = 0; + } + mantissa = mantissa_struct->m_1[mantissa_struct->m_1_pointer++]; + mantissa = mpeg3_q_1[mantissa]; + break; + + case 2: + if(mantissa_struct->m_2_pointer > 2) + { + group_code = mpeg3bits_getbits(audio->astream, 7); + + if(group_code > 124) + { + fprintf(stderr, "mpeg3audio_ac3_mantissa_get: Invalid mantissa 2 %d\n", group_code); + return 0; + } + + mantissa_struct->m_2[0] = group_code / 25; + mantissa_struct->m_2[1] = (group_code % 25) / 5; + mantissa_struct->m_2[2] = (group_code % 25) % 5; + mantissa_struct->m_2_pointer = 0; + } + mantissa = mantissa_struct->m_2[mantissa_struct->m_2_pointer++]; + mantissa = mpeg3_q_2[mantissa]; + break; + + case 3: + mantissa = mpeg3bits_getbits(audio->astream, 3); + + if(mantissa > 6) + { + fprintf(stderr, "mpeg3audio_ac3_mantissa_get: Invalid mantissa 3 %d\n", mantissa); + return 0; + } + + mantissa = mpeg3_q_3[mantissa]; + break; + + case 4: + if(mantissa_struct->m_4_pointer > 1) + { + group_code = mpeg3bits_getbits(audio->astream, 7); + + if(group_code > 120) + { + fprintf(stderr, "mpeg3audio_ac3_mantissa_get: Invalid mantissa 4 %d\n", group_code); + return 0; + } + + mantissa_struct->m_4[0] = group_code / 11; + mantissa_struct->m_4[1] = group_code % 11; + mantissa_struct->m_4_pointer = 0; + } + mantissa = mantissa_struct->m_4[mantissa_struct->m_4_pointer++]; + mantissa = mpeg3_q_4[mantissa]; + break; + + case 5: + mantissa = mpeg3bits_getbits(audio->astream, 4); + + if(mantissa > 14) + { +/* FIXME do proper block error handling */ + fprintf(stderr, "mpeg3audio_ac3_mantissa_get: Invalid mantissa 5 %d\n", mantissa); + return 0; + } + + mantissa = mpeg3_q_5[mantissa]; + break; + + default: + mantissa = mpeg3bits_getbits(audio->astream, mpeg3_qnttztab[bap]); + mantissa <<= 16 - mpeg3_qnttztab[bap]; + } + return mantissa; +} + +void mpeg3audio_ac3_uncouple_channel(mpeg3audio_t *audio, + mpeg3_real_t samples[], + mpeg3_ac3bsi_t *bsi, + mpeg3_ac3audblk_t *audblk, + unsigned int ch) +{ + unsigned int bnd = 0; + unsigned int sub_bnd = 0; + unsigned int i, j; + MPEG3_FLOAT32 cpl_coord = 1.0; + unsigned int cpl_exp_tmp; + unsigned int cpl_mant_tmp; + short mantissa; + + for(i = audblk->cplstrtmant; i < audblk->cplendmant; ) + { + if(!audblk->cplbndstrc[sub_bnd++]) + { + cpl_exp_tmp = audblk->cplcoexp[ch][bnd] + 3 * audblk->mstrcplco[ch]; + if(audblk->cplcoexp[ch][bnd] == 15) + cpl_mant_tmp = (audblk->cplcomant[ch][bnd]) << 11; + else + cpl_mant_tmp = ((0x10) | audblk->cplcomant[ch][bnd]) << 10; + + cpl_coord = mpeg3audio_ac3_tofloat(cpl_exp_tmp, cpl_mant_tmp) * 8.0f; + +/*Invert the phase for the right channel if necessary */ + if(bsi->acmod == 0x2 && audblk->phsflginu && ch == 1 && audblk->phsflg[bnd]) + cpl_coord *= -1; + + bnd++; + } + + for(j = 0; j < 12; j++) + { +/* Get new dither values for each channel if necessary, so */ +/* the channels are uncorrelated */ + if(audblk->dithflag[ch] && audblk->cpl_bap[i] == 0) + mantissa = mpeg3audio_ac3_dither_gen(audio); + else + mantissa = audblk->cplmant[i]; + + samples[i] = cpl_coord * mpeg3audio_ac3_tofloat(audblk->cpl_exp[i], mantissa);; + + i++; + } + } + return; +} + +int mpeg3audio_ac3_coeff_unpack(mpeg3audio_t *audio, + mpeg3_ac3bsi_t *bsi, + mpeg3_ac3audblk_t *audblk, + mpeg3ac3_stream_samples_t samples) +{ + int i, j; + int done_cpl = 0; + short mantissa; + + mpeg3audio_ac3_mantissa_reset(&(audio->ac3_mantissa)); + + for(i = 0; i < bsi->nfchans && !mpeg3bits_error(audio->astream); i++) + { + for(j = 0; j < audblk->endmant[i] && !mpeg3bits_error(audio->astream); j++) + { + mantissa = mpeg3audio_ac3_mantissa_get(audio, audblk->fbw_bap[i][j], audblk->dithflag[i]); + samples[i][j] = mpeg3audio_ac3_tofloat(audblk->fbw_exp[i][j], mantissa); + } + + if(audblk->cplinu && audblk->chincpl[i] && !(done_cpl) && !mpeg3bits_error(audio->astream)) + { +/* ncplmant is equal to 12 * ncplsubnd */ +/* Don't dither coupling channel until channel separation so that + * interchannel noise is uncorrelated */ + for(j = audblk->cplstrtmant; + j < audblk->cplendmant && !mpeg3bits_error(audio->astream); + j++) + { + audblk->cplmant[j] = mpeg3audio_ac3_mantissa_get(audio, audblk->cpl_bap[j], 0); + } + done_cpl = 1; + } + } + +/* Uncouple the channel */ + if(audblk->cplinu) + { + if(audblk->chincpl[i]) + mpeg3audio_ac3_uncouple_channel(audio, samples[i], bsi, audblk, i); + } + + if(bsi->lfeon && !mpeg3bits_error(audio->astream)) + { +/* There are always 7 mantissas for lfe, no dither for lfe */ + for(j = 0; j < 7 && !mpeg3bits_error(audio->astream); j++) + mantissa = mpeg3audio_ac3_mantissa_get(audio, audblk->lfe_bap[j], 0); + samples[5][j] = mpeg3audio_ac3_tofloat(audblk->lfe_exp[j], mantissa); + } + + return mpeg3bits_error(audio->astream); +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.c b/core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.c new file mode 100644 index 0000000..e2d3912 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.c @@ -0,0 +1,536 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3audio.h" +#include "tables.h" + +#include +#include + +mpeg3audio_t* mpeg3audio_allocate_struct(mpeg3_t *file, mpeg3_atrack_t *track) +{ + mpeg3audio_t *audio = (mpeg3audio_t*)calloc(1, sizeof(mpeg3audio_t)); + audio->file = file; + audio->track = track; + audio->astream = mpeg3bits_new_stream(file, track->demuxer); + audio->outscale = 1; + audio->bsbuf = audio->bsspace[1]; + audio->init = 1; + audio->bo = 1; + audio->channels = 1; + return audio; +} + + +int mpeg3audio_delete_struct(mpeg3audio_t *audio) +{ + mpeg3bits_delete_stream(audio->astream); + if(audio->pcm_sample) free(audio->pcm_sample); + free(audio); + return 0; +} + +int mpeg3audio_replace_buffer(mpeg3audio_t *audio, long new_allocation) +{ + long i; + + audio->pcm_sample = (mpeg3_real_t*)realloc( audio->pcm_sample, sizeof(mpeg3_real_t) * new_allocation * audio->channels ); + audio->pcm_allocated = new_allocation; +/* + // Isn't this exactly the same as what the ANSI C function call realloc does, + // or did I miss C Programming 101 ? + + if(!audio->pcm_sample) + { + audio->pcm_sample = (mpeg3_real_t*)malloc(sizeof(mpeg3_real_t) * new_allocation * audio->channels); + audio->pcm_allocated = new_allocation; + } + else + { + mpeg3_real_t *new_samples = (mpeg3_real_t*)malloc(sizeof(mpeg3_real_t) * new_allocation * audio->channels); + for(i = 0; i < audio->pcm_allocated * audio->channels; i++) + { + new_samples[i] = audio->pcm_sample[i]; + } + free(audio->pcm_sample); + audio->pcm_sample = new_samples; + audio->pcm_allocated = new_allocation; + } +*/ + return 0; +} + +int mpeg3audio_read_frame(mpeg3audio_t *audio) +{ + int result = 0; + result = mpeg3audio_read_header(audio); + + if(!result) + { + switch(audio->format) + { + case AUDIO_AC3: + result = mpeg3audio_do_ac3(audio); + break; + + case AUDIO_MPEG: + switch(audio->layer) + { + case 1: + break; + + case 2: + result = mpeg3audio_dolayer2(audio); + break; + + case 3: + result = mpeg3audio_dolayer3(audio); + break; + + default: + result = 1; + break; + } + break; + + case AUDIO_PCM: + result = mpeg3audio_do_pcm(audio); + break; + } + } + + if(!result) + { +/* Byte align the stream */ + mpeg3bits_byte_align(audio->astream); + } + return result; +} + +/* Get the length but also initialize the frame sizes. */ +int mpeg3audio_get_length(mpeg3audio_t *audio, mpeg3_atrack_t *track) +{ + long result = 0; + long framesize1 = 0, total1 = 0; + long framesize2 = 0, total2 = 0; + long total_framesize = 0, total_frames = 0; + long byte_limit = 131072; /* Total bytes to gather information from */ + long total_bytes = 0; + long major_framesize; /* Bigger framesize + header */ + long minor_framesize; /* Smaller framesize + header */ + long major_total; + long minor_total; + mpeg3_t *file = audio->file; + +/* Get the frame sizes */ + mpeg3bits_seek_start(audio->astream); + audio->pcm_point = 0; + result = mpeg3audio_read_frame(audio); /* Stores the framesize */ + audio->samples_per_frame = audio->pcm_point / audio->channels; + + switch(audio->format) + { + case AUDIO_AC3: + audio->avg_framesize = audio->framesize; + break; + + case AUDIO_MPEG: + framesize1 = audio->framesize; + total_bytes += audio->framesize; + total1 = 1; + + while(!result && total_bytes < byte_limit) + { + audio->pcm_point = 0; + result = mpeg3audio_read_frame(audio); + total_bytes += audio->framesize; + if(audio->framesize != framesize1) + { + framesize2 = audio->framesize; + total2 = 1; + break; + } + else + { + total1++; + } + } + + while(!result && total_bytes < byte_limit) + { + audio->pcm_point = 0; + result = mpeg3audio_read_frame(audio); + total_bytes += audio->framesize; + if(audio->framesize != framesize2) + { + break; + } + else + { + total2++; + } + } + + audio->pcm_point = 0; + result = mpeg3audio_read_frame(audio); + if(audio->framesize != framesize1 && audio->framesize != framesize2) + { +/* Variable bit rate. Get the average frame size. */ + while(!result && total_bytes < byte_limit) + { + audio->pcm_point = 0; + result = mpeg3audio_read_frame(audio); + total_bytes += audio->framesize; + if(!result) + { + total_framesize += audio->framesize; + total_frames++; + } + } + audio->avg_framesize = 4 + (total_framesize + framesize1 + framesize2) / (total_frames + total1 + total2); + } + else + { + major_framesize = framesize2 > framesize1 ? framesize2 : framesize1; + major_total = framesize2 > framesize1 ? total2 : total1; + minor_framesize = framesize2 > framesize1 ? framesize1 : framesize2; + minor_total = framesize2 > framesize1 ? total1 : total2; +/* Add the headers to the framesizes */ + audio->avg_framesize = 4 + (major_framesize * major_total + minor_framesize * minor_total) / (major_total + minor_total); + } + break; + + case AUDIO_PCM: + break; + } + +/* Estimate the total samples */ + if(file->is_audio_stream) + { +/* From the raw file */ + result = (long)((float)mpeg3demuxer_total_bytes(audio->astream->demuxer) / audio->avg_framesize * audio->samples_per_frame); + } + else + { +/* Gross approximation from a multiplexed file. */ + result = (long)(mpeg3demux_length(audio->astream->demuxer) * track->sample_rate); +/* result = (long)((mpeg3_real_t)mpeg3_video_frames(file, 0) / mpeg3_frame_rate(file, 0) * track->sample_rate); */ +/* We would scan the multiplexed packets here for the right timecode if only */ +/* they had meaningful timecode. */ + } + + audio->pcm_point = 0; + mpeg3bits_seek_start(audio->astream); + mpeg3audio_reset_synths(audio); + return result; +} + +int mpeg3audio_seek(mpeg3audio_t *audio, long position) +{ + int result = 0; + mpeg3_t *file = audio->file; + mpeg3_atrack_t *track = audio->track; + long frame_number; + long byte_position; + double time_position; + +/* Sample seek wasn't requested */ + if(audio->sample_seek < 0) + { + audio->pcm_position = position; + audio->pcm_size = 0; + return 0; + } + +/* Can't slide buffer. Seek instead. */ + if(!file->is_audio_stream) + { +/* Seek in a multiplexed stream using the multiplexer. */ + time_position = (double)position / track->sample_rate; + result |= mpeg3bits_seek_time(audio->astream, time_position); + audio->pcm_position = (long)mpeg3bits_packet_time(audio->astream) * track->sample_rate; +/*printf("wanted %f got %f\n", time_position, mpeg3bits_packet_time(audio->astream)); */ + } + else + { +/* Seek in an elemental stream. This algorithm achieves sample accuracy on fixed bitrates. */ +/* Forget about variable bitrates or program streams. */ + frame_number = position / audio->samples_per_frame; + byte_position = (long)(audio->avg_framesize * frame_number); + audio->pcm_position = frame_number * audio->samples_per_frame; + + if(byte_position < audio->avg_framesize * 2) + { + result |= mpeg3bits_seek_start(audio->astream); + audio->pcm_position = 0; + } + else + { + result |= mpeg3bits_seek_byte(audio->astream, byte_position); + } + } + +/* Arm the backstep buffer for layer 3 if not at the beginning already. */ + if(byte_position >= audio->avg_framesize * 2 && audio->layer == 3 && !result) + { + result |= mpeg3audio_prev_header(audio); + result |= mpeg3audio_read_layer3_frame(audio); + } + +/* Reset the tables. */ + mpeg3audio_reset_synths(audio); + audio->pcm_size = 0; + audio->pcm_point = 0; + return result; +} + +/* ================================================================ */ +/* ENTRY POINTS */ +/* ================================================================ */ + + + + +mpeg3audio_t* mpeg3audio_new(mpeg3_t *file, mpeg3_atrack_t *track, int format) +{ + mpeg3audio_t *audio = mpeg3audio_allocate_struct(file, track); + int result = 0; + +/* Init tables */ + mpeg3audio_new_decode_tables(audio); + audio->percentage_seek = -1; + audio->sample_seek = -1; + audio->format = format; + +/* Determine the format of the stream */ + if(format == AUDIO_UNKNOWN) + { + if(((mpeg3bits_showbits(audio->astream, 32) & 0xffff0000) >> 16) == MPEG3_AC3_START_CODE) + audio->format = AUDIO_AC3; + else + audio->format = AUDIO_MPEG; + } + +/* get channel count */ + result = mpeg3audio_read_header(audio); + +/* Set up the sample buffer */ + mpeg3audio_replace_buffer(audio, 262144); + +/* Copy information to the mpeg struct */ + if(!result) + { + track->channels = audio->channels; + + switch(audio->format) + { + case AUDIO_AC3: + track->sample_rate = mpeg3_ac3_samplerates[audio->sampling_frequency_code]; + break; + + case AUDIO_MPEG: + track->sample_rate = mpeg3_freqs[audio->sampling_frequency_code]; + break; + + case AUDIO_PCM: + track->sample_rate = 48000; + break; + } + + track->total_samples = mpeg3audio_get_length(audio, track); + result |= mpeg3bits_seek_start(audio->astream); + } + else + { + mpeg3audio_delete_struct(audio); + audio = 0; + } + + return audio; +} + +int mpeg3audio_delete(mpeg3audio_t *audio) +{ + mpeg3audio_delete_struct(audio); + return 0; +} + +int mpeg3audio_seek_percentage(mpeg3audio_t *audio, double percentage) +{ + audio->percentage_seek = percentage; + return 0; +} + +int mpeg3audio_seek_sample(mpeg3audio_t *audio, long sample) +{ + audio->sample_seek = sample; + return 0; +} + +/* Read raw frames for concatenation purposes */ +int mpeg3audio_read_raw(mpeg3audio_t *audio, unsigned char *output, long *size, long max_size) +{ + int result = 0; + int i; + *size = 0; + + switch(audio->format) + { + case AUDIO_AC3: +/* Just write the AC3 stream */ + if(mpeg3bits_read_buffer(audio->astream, output, audio->framesize)) + return 1; + *size = audio->framesize; + break; + + case AUDIO_MPEG: +/* Fix the mpeg stream */ + result = mpeg3audio_read_header(audio); + if(!result) + { + if(max_size < 4) return 1; + *output++ = (audio->newhead & 0xff000000) >> 24; + *output++ = (audio->newhead & 0xff0000) >> 16; + *output++ = (audio->newhead & 0xff00) >> 8; + *output++ = (audio->newhead & 0xff); + *size += 4; + + if(max_size < 4 + audio->framesize) return 1; + if(mpeg3bits_read_buffer(audio->astream, output, audio->framesize)) + return 1; + + *size += audio->framesize; + } + break; + + case AUDIO_PCM: + if(mpeg3bits_read_buffer(audio->astream, output, audio->framesize)) + return 1; + *size = audio->framesize; + break; + } + return result; +} + +/* Channel is 0 to channels - 1 */ +int mpeg3audio_decode_audio(mpeg3audio_t *audio, + mpeg3_real_t *output_f, + short *output_i, int sampleSpacing, + int channel, + long start_position, + long len) +{ + long allocation_needed = len + MPEG3AUDIO_PADDING; + long i, j, result = 0; + mpeg3_t *file = audio->file; + mpeg3_atrack_t *atrack = audio->track; + long attempts; + +/* Create new buffer */ + if(audio->pcm_allocated < allocation_needed) + { + mpeg3audio_replace_buffer(audio, allocation_needed); + } + +/* There was a percentage seek */ + if(audio->percentage_seek >= 0) + { + mpeg3bits_seek_percentage(audio->astream, audio->percentage_seek); +/* Force the pcm buffer to be reread. */ + audio->pcm_position = start_position; + audio->pcm_size = 0; + audio->percentage_seek = -1; + } + else + { +/* Entire output is in buffer so don't do anything. */ + if(start_position >= audio->pcm_position && start_position < audio->pcm_position + audio->pcm_size && + start_position + len <= audio->pcm_size) + { + ; + } + else +/* Output starts in buffer but ends later so slide it back. */ + if(start_position <= audio->pcm_position + audio->pcm_size && + start_position >= audio->pcm_position) + { + for(i = 0, j = (start_position - audio->pcm_position) * audio->channels; + j < audio->pcm_size * audio->channels; + i++, j++) + { + audio->pcm_sample[i] = audio->pcm_sample[j]; + } + + audio->pcm_point = i; + audio->pcm_size -= start_position - audio->pcm_position; + audio->pcm_position = start_position; + } + else + { +/* Output is outside buffer completely. */ + result = mpeg3audio_seek(audio, start_position); + audio->sample_seek = -1; +/* Check sanity */ + if(start_position < audio->pcm_position) audio->pcm_position = start_position; + } + audio->sample_seek = -1; + } + +/* Read packets until the buffer is full. */ + if(!result) + { + attempts = 0; + result = 1; + while(attempts < 6 && + !mpeg3bits_eof(audio->astream) && + audio->pcm_size + audio->pcm_position < start_position + len) + { + result = mpeg3audio_read_frame(audio); + if(result) attempts++; + audio->pcm_size = audio->pcm_point / audio->channels; + } + } + + + +/* Copy the buffer to the output */ + if(output_f) + { + for(i = 0, j = (start_position - audio->pcm_position) * audio->channels + channel; + i < len && j < audio->pcm_size * audio->channels; + i++, j += audio->channels) + { + output_f[i] = audio->pcm_sample[j]; + } + for( ; i < len; i++) + { + output_f[i] = 0; + } + } + else + if(output_i) + { + int sample; + for(i = 0, j = (start_position - audio->pcm_position) * audio->channels + channel; + i < (len*(sampleSpacing+1)) && j < audio->pcm_size * audio->channels; + i++, j += audio->channels) + { + sample = (int)(audio->pcm_sample[j] * 32767); + if(sample > 32767) sample = 32767; + else + if(sample < -32768) sample = -32768; + + output_i[i] = sample; + i += sampleSpacing; + } + for( ; i < (len*(sampleSpacing+1)); i++) + { + output_i[i] = 0; + i += sampleSpacing; + } + } + + if(audio->pcm_point > 0) + return 0; + else + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.h b/core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.h new file mode 100644 index 0000000..2117be7 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.h @@ -0,0 +1,144 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3AUDIO_H +#define MPEG3AUDIO_H + +#include "ac3.h" +#include "../bitstream.h" +typedef struct mpeg3_atrack_rec mpeg3_atrack_t; + +#define MAXFRAMESIZE 1792 +#define HDRCMPMASK 0xfffffd00 +#define SBLIMIT 32 +#define SSLIMIT 18 +#define SCALE_BLOCK 12 +#define MPEG3AUDIO_PADDING 1024 + +/* Values for mode */ +#define MPG_MD_STEREO 0 +#define MPG_MD_JOINT_STEREO 1 +#define MPG_MD_DUAL_CHANNEL 2 +#define MPG_MD_MONO 3 + +/* IMDCT variables */ +typedef struct +{ + mpeg3_real_t real; + mpeg3_real_t imag; +} mpeg3_complex_t; + +#define AC3_N 512 + +struct al_table +{ + short bits; + short d; +}; + +typedef struct +{ + struct mpeg3_rec* file; + mpeg3_atrack_t* track; + mpeg3_bits_t *astream; + +/* In order of importance */ + int format; /* format of audio */ + int layer; /* layer if mpeg */ + int channels; + long outscale; + long framenum; + long prev_framesize; + long framesize; /* For mp3 current framesize without header. For AC3 current framesize with header. */ + int avg_framesize; /* Includes the 4 byte header */ + mpeg3_real_t *pcm_sample; /* Interlaced output from synthesizer in floats */ + int pcm_point; /* Float offset in pcm_sample to write to */ + long pcm_position; /* Sample start of pcm_samples in file */ + long pcm_size; /* Number of pcm samples in the buffer */ + long pcm_allocated; /* Allocated number of samples in pcm_samples */ + int sample_seek; + double percentage_seek; + unsigned long oldhead; + unsigned long newhead; + unsigned long firsthead; + int bsnum; + int lsf; + int mpeg35; + int sampling_frequency_code; + int bitrate_index; + int bitrate; + int samples_per_frame; + int padding; + int extension; + int mode; + int mode_ext; + int copyright; + int original; + int emphasis; + int error_protection; + +/* Back step buffers for mp3 */ + unsigned char bsspace[2][MAXFRAMESIZE + 512]; /* MAXFRAMESIZE */ + unsigned char *bsbuf, *bsbufold; + long ssize; + int init; + int single; + struct al_table *alloc; + int II_sblimit; + int jsbound; + int bo; /* Static variable in synthesizer */ + +/* MP3 Static arrays here */ + mpeg3_real_t synth_stereo_buffs[2][2][0x110]; + mpeg3_real_t synth_mono_buff[64]; + unsigned int layer2_scfsi_buf[64]; + + mpeg3_real_t mp3_block[2][2][SBLIMIT * SSLIMIT]; + int mp3_blc[2]; + +/* AC3 specific stuff. AC3 also shares objects with MPEG */ + unsigned int ac3_framesize_code; + mpeg3_ac3bsi_t ac3_bsi; + mpeg3_ac3audblk_t ac3_audblk; + mpeg3_ac3_bitallocation_t ac3_bit_allocation; + mpeg3_ac3_mantissa_t ac3_mantissa; + mpeg3_complex_t ac3_imdct_buf[AC3_N / 4]; + +/* Delay buffer for DCT interleaving */ + mpeg3_real_t ac3_delay[6][AC3_N / 2]; +/* Twiddle factor LUT */ + mpeg3_complex_t *ac3_w[7]; +#if !defined(USE_FIXED_POINT) || defined(PRINT_FIXED_POINT_TABLES) + /* Just for allocated memory */ + mpeg3_complex_t ac3_w_1[1]; + mpeg3_complex_t ac3_w_2[2]; + mpeg3_complex_t ac3_w_4[4]; + mpeg3_complex_t ac3_w_8[8]; + mpeg3_complex_t ac3_w_16[16]; + mpeg3_complex_t ac3_w_32[32]; + mpeg3_complex_t ac3_w_64[64]; +#endif + int ac3_lfsr_state; + unsigned char ac3_buffer[MAX_AC3_FRAMESIZE]; + mpeg3ac3_stream_samples_t ac3_samples; +} mpeg3audio_t; + + + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/audio/mpeg3real.h b/core/multimedia/opieplayer/libmpeg3/audio/mpeg3real.h new file mode 100644 index 0000000..cdcac3d --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/mpeg3real.h @@ -0,0 +1,232 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3REAL_H +#define MPEG3REAL_H + +#ifdef USE_FIXED_POINT + +#include +#include + +#ifndef LONGLONG +#define LONGLONG long long +#endif + +//#define SC (1<<16) +#define SC (1<<15) + +class mpeg3_real_t { + long v; +public: + mpeg3_real_t() { } // Uninitialized, just like a float + mpeg3_real_t(double d) { v=long(d*SC); } + mpeg3_real_t(float f) { v=long(f*SC); } + mpeg3_real_t(int i) { v=long(i*SC); } + long fixedPoint() const { return v; } + operator float() const { return ((float)v)/SC; } + operator int() const { return (int)(v/SC); } + mpeg3_real_t operator+() const; + mpeg3_real_t operator-() const; + mpeg3_real_t& operator= (const mpeg3_real_t&); + mpeg3_real_t& operator+= (const mpeg3_real_t&); + mpeg3_real_t& operator-= (const mpeg3_real_t&); + mpeg3_real_t& operator*= (const mpeg3_real_t&); + mpeg3_real_t& operator/= (const mpeg3_real_t&); + friend mpeg3_real_t operator+ (const mpeg3_real_t&, const mpeg3_real_t&); + friend mpeg3_real_t operator- (const mpeg3_real_t&, const mpeg3_real_t&); + friend mpeg3_real_t operator* (const mpeg3_real_t&, const mpeg3_real_t&); + friend mpeg3_real_t operator/ (const mpeg3_real_t&, const mpeg3_real_t&); + friend mpeg3_real_t operator+ (const mpeg3_real_t&, const float&); + friend mpeg3_real_t operator- (const mpeg3_real_t&, const float&); + friend mpeg3_real_t operator* (const mpeg3_real_t&, const float&); + friend mpeg3_real_t operator/ (const mpeg3_real_t&, const float&); + friend mpeg3_real_t operator+ (const float&, const mpeg3_real_t&); + friend mpeg3_real_t operator- (const float&, const mpeg3_real_t&); + friend mpeg3_real_t operator* (const float&, const mpeg3_real_t&); + friend mpeg3_real_t operator/ (const float&, const mpeg3_real_t&); + friend mpeg3_real_t operator+ (const mpeg3_real_t&, const int&); + friend mpeg3_real_t operator- (const mpeg3_real_t&, const int&); + friend mpeg3_real_t operator* (const mpeg3_real_t&, const int&); + friend mpeg3_real_t operator/ (const mpeg3_real_t&, const int&); + friend mpeg3_real_t operator+ (const int&, const mpeg3_real_t&); + friend mpeg3_real_t operator- (const int&, const mpeg3_real_t&); + friend mpeg3_real_t operator* (const int&, const mpeg3_real_t&); + friend mpeg3_real_t operator/ (const int&, const mpeg3_real_t&); +}; + +inline mpeg3_real_t mpeg3_real_t::operator+() const +{ + return *this; +} + +inline mpeg3_real_t mpeg3_real_t::operator-() const +{ + mpeg3_real_t r; + r.v=-v; + return r; +} + +inline mpeg3_real_t& mpeg3_real_t::operator= (const mpeg3_real_t& o) +{ + v=o.v; + return *this; +} + +inline mpeg3_real_t& mpeg3_real_t::operator+= (const mpeg3_real_t& o) +{ + v += o.v; + return *this; +} + +inline mpeg3_real_t& mpeg3_real_t::operator-= (const mpeg3_real_t& o) +{ + v -= o.v; + return *this; +} + +inline mpeg3_real_t& mpeg3_real_t::operator*= (const mpeg3_real_t& o) +{ + *this = *this * o; + return *this; +} + +inline mpeg3_real_t& mpeg3_real_t::operator/= (const mpeg3_real_t& o) +{ + *this = *this / o; + return *this; +} + + +inline mpeg3_real_t operator+ (const mpeg3_real_t&a, const mpeg3_real_t&b) +{ + mpeg3_real_t r; + r.v=a.v+b.v; + return r; +} + +inline mpeg3_real_t operator- (const mpeg3_real_t&a, const mpeg3_real_t&b) +{ + mpeg3_real_t r; + r.v=a.v-b.v; + return r; +} + +inline mpeg3_real_t operator* (const mpeg3_real_t&a, const mpeg3_real_t&b) +{ + mpeg3_real_t r; + r.v = (LONGLONG)a.v * b.v / SC; + return r; +} + +inline mpeg3_real_t operator/ (const mpeg3_real_t&a, const mpeg3_real_t&b) +{ + mpeg3_real_t r; + r.v = (LONGLONG)a.v * SC / b.v; + return r; +} + +inline mpeg3_real_t operator+ (const mpeg3_real_t&a, const float&b) +{ + return a+mpeg3_real_t(b); +} + +inline mpeg3_real_t operator- (const mpeg3_real_t&a, const float&b) +{ + return a-mpeg3_real_t(b); +} + +inline mpeg3_real_t operator* (const mpeg3_real_t&a, const float&b) +{ + return a*mpeg3_real_t(b); +} + +inline mpeg3_real_t operator/ (const mpeg3_real_t&a, const float&b) +{ + return a/mpeg3_real_t(b); +} + + +inline mpeg3_real_t operator+ (const float&a, const mpeg3_real_t&b) +{ + return mpeg3_real_t(a)+b; +} + +inline mpeg3_real_t operator- (const float&a, const mpeg3_real_t&b) +{ + return mpeg3_real_t(a)-b; +} + +inline mpeg3_real_t operator* (const float&a, const mpeg3_real_t&b) +{ + return mpeg3_real_t(a)*b; +} + +inline mpeg3_real_t operator/ (const float&a, const mpeg3_real_t&b) +{ + return mpeg3_real_t(a)/b; +} + + +inline mpeg3_real_t operator+ (const mpeg3_real_t&a, const int&b) +{ + return a+mpeg3_real_t(b); +} + +inline mpeg3_real_t operator- (const mpeg3_real_t&a, const int&b) +{ + return a-mpeg3_real_t(b); +} + +inline mpeg3_real_t operator* (const mpeg3_real_t&a, const int&b) +{ + return a*mpeg3_real_t(b); +} + +inline mpeg3_real_t operator/ (const mpeg3_real_t&a, const int&b) +{ + return a/mpeg3_real_t(b); +} + + +inline mpeg3_real_t operator+ (const int&a, const mpeg3_real_t&b) +{ + return mpeg3_real_t(a)+b; +} + +inline mpeg3_real_t operator- (const int&a, const mpeg3_real_t&b) +{ + return mpeg3_real_t(a)-b; +} + +inline mpeg3_real_t operator* (const int&a, const mpeg3_real_t&b) +{ + return mpeg3_real_t(a)*b; +} + +inline mpeg3_real_t operator/ (const int&a, const mpeg3_real_t&b) +{ + return mpeg3_real_t(a)/b; +} + +#else +typedef float mpeg3_real_t; +#endif + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/audio/pcm.c b/core/multimedia/opieplayer/libmpeg3/audio/pcm.c new file mode 100644 index 0000000..8fa0d25 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/pcm.c @@ -0,0 +1,51 @@ +#include "mpeg3audio.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" + +int mpeg3audio_read_pcm_header(mpeg3audio_t *audio) +{ + unsigned int code; + + code = mpeg3bits_getbits(audio->astream, 16); + while(!mpeg3bits_eof(audio->astream) && code != MPEG3_PCM_START_CODE) + { + code <<= 8; + code &= 0xffff; + code |= mpeg3bits_getbits(audio->astream, 8); + } + + audio->avg_framesize = audio->framesize = 0x7db; + audio->channels = 2; + + return mpeg3bits_eof(audio->astream); +} + +int mpeg3audio_do_pcm(mpeg3audio_t *audio) +{ + int i, j, k; + MPEG3_INT16 sample; + int frame_samples = (audio->framesize - 3) / audio->channels / 2; + + if(mpeg3bits_read_buffer(audio->astream, audio->ac3_buffer, frame_samples * audio->channels * 2)) + return 1; + +/* Need more room */ + if(audio->pcm_point / audio->channels >= audio->pcm_allocated - MPEG3AUDIO_PADDING * audio->channels) + { + mpeg3audio_replace_buffer(audio, audio->pcm_allocated + MPEG3AUDIO_PADDING * audio->channels); + } + + k = 0; + for(i = 0; i < frame_samples; i++) + { + for(j = 0; j < audio->channels; j++) + { + sample = ((MPEG3_INT16)(audio->ac3_buffer[k++])) << 8; + sample |= audio->ac3_buffer[k++]; + audio->pcm_sample[audio->pcm_point + i * audio->channels + j] = + (mpeg3_real_t)sample / 32767; + } + } + audio->pcm_point += frame_samples * audio->channels; + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/synthesizers.c b/core/multimedia/opieplayer/libmpeg3/audio/synthesizers.c new file mode 100644 index 0000000..71a74b3 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/synthesizers.c @@ -0,0 +1,174 @@ +#include "mpeg3audio.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "tables.h" + +#define WRITE_SAMPLE(samples, sum) \ +{ \ + (*samples) = (sum); \ +} + +int mpeg3audio_synth_stereo(mpeg3audio_t *audio, mpeg3_real_t *bandPtr, int channel, mpeg3_real_t *out, int *pnt) +{ + const int step = 2; + mpeg3_real_t *samples = out + *pnt; + register mpeg3_real_t sum; + mpeg3_real_t *b0, (*buf)[0x110]; + int bo1; + + if(!channel) + { + audio->bo--; + audio->bo &= 0xf; + buf = audio->synth_stereo_buffs[0]; + } + else + { + samples++; + buf = audio->synth_stereo_buffs[1]; + } + + if(audio->bo & 0x1) + { + b0 = buf[0]; + bo1 = audio->bo; + mpeg3audio_dct64(buf[1] + ((audio->bo + 1) & 0xf), buf[0] + audio->bo, bandPtr); + } + else + { + b0 = buf[1]; + bo1 = audio->bo + 1; + mpeg3audio_dct64(buf[0] + audio->bo, buf[1] + audio->bo + 1, bandPtr); + } + +/*printf("%f %f %f\n", buf[0][0], buf[1][0], bandPtr[0]); */ + + { + register int j; + mpeg3_real_t *window = mpeg3_decwin + 16 - bo1; + + for(j = 16; j; j--, b0 += 0x10, window += 0x20, samples += step) + { + sum = window[0x0] * b0[0x0]; + sum -= window[0x1] * b0[0x1]; + sum += window[0x2] * b0[0x2]; + sum -= window[0x3] * b0[0x3]; + sum += window[0x4] * b0[0x4]; + sum -= window[0x5] * b0[0x5]; + sum += window[0x6] * b0[0x6]; + sum -= window[0x7] * b0[0x7]; + sum += window[0x8] * b0[0x8]; + sum -= window[0x9] * b0[0x9]; + sum += window[0xA] * b0[0xA]; + sum -= window[0xB] * b0[0xB]; + sum += window[0xC] * b0[0xC]; + sum -= window[0xD] * b0[0xD]; + sum += window[0xE] * b0[0xE]; + sum -= window[0xF] * b0[0xF]; + + WRITE_SAMPLE(samples, sum); + } + + sum = window[0x0] * b0[0x0]; + sum += window[0x2] * b0[0x2]; + sum += window[0x4] * b0[0x4]; + sum += window[0x6] * b0[0x6]; + sum += window[0x8] * b0[0x8]; + sum += window[0xA] * b0[0xA]; + sum += window[0xC] * b0[0xC]; + sum += window[0xE] * b0[0xE]; + WRITE_SAMPLE(samples, sum); + b0 -= 0x10; + window -= 0x20; + samples += step; + window += bo1 << 1; + + for(j = 15; j; j--, b0 -= 0x10, window -= 0x20, samples += step) + { + sum = -window[-0x1] * b0[0x0]; + sum -= window[-0x2] * b0[0x1]; + sum -= window[-0x3] * b0[0x2]; + sum -= window[-0x4] * b0[0x3]; + sum -= window[-0x5] * b0[0x4]; + sum -= window[-0x6] * b0[0x5]; + sum -= window[-0x7] * b0[0x6]; + sum -= window[-0x8] * b0[0x7]; + sum -= window[-0x9] * b0[0x8]; + sum -= window[-0xA] * b0[0x9]; + sum -= window[-0xB] * b0[0xA]; + sum -= window[-0xC] * b0[0xB]; + sum -= window[-0xD] * b0[0xC]; + sum -= window[-0xE] * b0[0xD]; + sum -= window[-0xF] * b0[0xE]; + sum -= window[-0x0] * b0[0xF]; + + WRITE_SAMPLE(samples, sum); + } + } + *pnt += 64; + + return 0; +} + +int mpeg3audio_synth_mono(mpeg3audio_t *audio, mpeg3_real_t *bandPtr, mpeg3_real_t *samples, int *pnt) +{ + mpeg3_real_t *samples_tmp = audio->synth_mono_buff; + mpeg3_real_t *tmp1 = samples_tmp; + int i, ret; + int pnt1 = 0; + + ret = mpeg3audio_synth_stereo(audio, bandPtr, 0, samples_tmp, &pnt1); + samples += *pnt; + + for(i = 0; i < 32; i++) + { + *samples = *tmp1; + samples++; + tmp1 += 2; + } + *pnt += 32; + + return ret; +} + + +/* Call this after every seek to reset the buffers */ +int mpeg3audio_reset_synths(mpeg3audio_t *audio) +{ + int i, j, k; + for(i = 0; i < 2; i++) + { + for(j = 0; j < 2; j++) + { + for(k = 0; k < 0x110; k++) + { + audio->synth_stereo_buffs[i][j][k] = 0; + } + } + } + for(i = 0; i < 64; i++) + { + audio->synth_mono_buff[i] = 0; + audio->layer2_scfsi_buf[i] = 0; + } + for(i = 0; i < 2; i++) + { + for(j = 0; j < 2; j++) + { + for(k = 0; k < SBLIMIT * SSLIMIT; k++) + { + audio->mp3_block[i][j][k] = 0; + } + } + } + audio->mp3_blc[0] = 0; + audio->mp3_blc[1] = 0; + for(i = 0; i < audio->channels; i++) + { + for(j = 0; j < AC3_N / 2; j++) + { + audio->ac3_delay[i][j] = 0; + } + } + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/tables.c b/core/multimedia/opieplayer/libmpeg3/audio/tables.c new file mode 100644 index 0000000..aeab335 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/tables.c @@ -0,0 +1,554 @@ +#include "mpeg3audio.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "tables.h" + +#include + +/* Bitrate indexes */ +int mpeg3_tabsel_123[2][3][16] = { + { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, + {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,}, + {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} }, + + { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, + {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, + {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} } +}; + +long mpeg3_freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 }; + +#ifdef USE_3DNOW +mpeg3_real_t mpeg3_decwin[2 * (512 + 32)]; +mpeg3_real_t mpeg3_cos64[32], mpeg3_cos32[16], mpeg3_cos16[8], mpeg3_cos8[4], mpeg3_cos4[2]; +#else +mpeg3_real_t mpeg3_decwin[512 + 32]; +mpeg3_real_t mpeg3_cos64[16], mpeg3_cos32[8], mpeg3_cos16[4], mpeg3_cos8[2], mpeg3_cos4[1]; +#endif + +mpeg3_real_t *mpeg3_pnts[] = { mpeg3_cos64, mpeg3_cos32, mpeg3_cos16, mpeg3_cos8, mpeg3_cos4 }; + +int mpeg3_grp_3tab[32 * 3] = { 0, }; /* used: 27 */ +int mpeg3_grp_5tab[128 * 3] = { 0, }; /* used: 125 */ +int mpeg3_grp_9tab[1024 * 3] = { 0, }; /* used: 729 */ + +REAL_MATRIX(mpeg3_muls, [27], [64]); /* also used by layer 1 */ +REAL_MATRIX(mpeg3_gainpow2, [256 + 118 + 4], ); +REAL_MATRIX(mpeg3_ispow, [8207], ); +REAL_MATRIX(mpeg3_aa_ca, [8], ); +REAL_MATRIX(mpeg3_aa_cs, [8], ); +REAL_MATRIX(mpeg3_win, [4], [36]); +REAL_MATRIX(mpeg3_win1, [4], [36]); +REAL_MATRIX(mpeg3_COS1, [12], [6]); +REAL_MATRIX(mpeg3_COS9, [9], ); +REAL_MATRIX(mpeg3_tfcos36, [9], ); +REAL_MATRIX(mpeg3_tfcos12, [3], ); +REAL_MATRIX(mpeg3_cos9, [3], ); +REAL_MATRIX(mpeg3_cos18, [3], ); +REAL_MATRIX(mpeg3_tan1_1, [16], ); +REAL_MATRIX(mpeg3_tan2_1, [16], ); +REAL_MATRIX(mpeg3_tan1_2, [16], ); +REAL_MATRIX(mpeg3_tan2_2, [16], ); +REAL_MATRIX(mpeg3_pow1_1, [2], [16]); +REAL_MATRIX(mpeg3_pow2_1, [2], [16]); +REAL_MATRIX(mpeg3_pow1_2, [2], [16]); +REAL_MATRIX(mpeg3_pow2_2, [2], [16]); + +mpeg3_real_t mpeg3_COS6_1, mpeg3_COS6_2; + +#ifdef PRINT_FIXED_POINT_TABLES +static void print_table(const char* var, mpeg3_real_t* data, int count) +{ + int i; + printf("#ifdef USE_DATA_TABLES\n"); + printf("static long %s_data[] = {",var); + for(i = 0; i < count; i++) { + printf("%c0x%08x,", i%8?' ':'\n', data[i].fixedPoint()); + } + printf("};\n"); + printf("#endif\n"); +} +#endif + +#ifdef PRINT_FIXED_POINT_TABLES +# define DO_TABLE(T) print_table(#T, T, sizeof(T)/sizeof(mpeg3_real_t)) +# define DO_TABLE2(T,DIM) print_table(#T, (mpeg3_real_t*)T, sizeof(T)/sizeof(mpeg3_real_t)) +#elif USE_FIXED_POINT +# define DO_TABLE(T) T = (mpeg3_real_t*)T##_data + // multidimensional +# define DO_TABLE2(T,DIM) T = (mpeg3_real_t(*)DIM)T##_data +#else +# define DO_TABLE(T) +# define DO_TABLE2(T,DIM) +#endif + +#if defined(USE_FIXED_POINT) && !defined(PRINT_FIXED_POINT_TABLES) +#define USE_DATA_TABLES +#include "fptables.h" +#endif + +long mpeg3_intwinbase[] = { + 0, -1, -1, -1, -1, -1, -1, -2, -2, -2, + -2, -3, -3, -4, -4, -5, -5, -6, -7, -7, + -8, -9, -10, -11, -13, -14, -16, -17, -19, -21, + -24, -26, -29, -31, -35, -38, -41, -45, -49, -53, + -58, -63, -68, -73, -79, -85, -91, -97, -104, -111, + -117, -125, -132, -139, -147, -154, -161, -169, -176, -183, + -190, -196, -202, -208, -213, -218, -222, -225, -227, -228, + -228, -227, -224, -221, -215, -208, -200, -189, -177, -163, + -146, -127, -106, -83, -57, -29, 2, 36, 72, 111, + 153, 197, 244, 294, 347, 401, 459, 519, 581, 645, + 711, 779, 848, 919, 991, 1064, 1137, 1210, 1283, 1356, + 1428, 1498, 1567, 1634, 1698, 1759, 1817, 1870, 1919, 1962, + 2001, 2032, 2057, 2075, 2085, 2087, 2080, 2063, 2037, 2000, + 1952, 1893, 1822, 1739, 1644, 1535, 1414, 1280, 1131, 970, + 794, 605, 402, 185, -45, -288, -545, -814, -1095, -1388, + -1692, -2006, -2330, -2663, -3004, -3351, -3705, -4063, -4425, -4788, + -5153, -5517, -5879, -6237, -6589, -6935, -7271, -7597, -7910, -8209, + -8491, -8755, -8998, -9219, -9416, -9585, -9727, -9838, -9916, -9959, + -9966, -9935, -9863, -9750, -9592, -9389, -9139, -8840, -8492, -8092, + -7640, -7134, -6574, -5959, -5288, -4561, -3776, -2935, -2037, -1082, + -70, 998, 2122, 3300, 4533, 5818, 7154, 8540, 9975, 11455, + 12980, 14548, 16155, 17799, 19478, 21189, 22929, 24694, 26482, 28289, + 30112, 31947, 33791, 35640, 37489, 39336, 41176, 43006, 44821, 46617, + 48390, 50137, 51853, 53534, 55178, 56778, 58333, 59838, 61289, 62684, + 64019, 65290, 66494, 67629, 68692, 69679, 70590, 71420, 72169, 72835, + 73415, 73908, 74313, 74630, 74856, 74992, 75038 }; + +int mpeg3_longLimit[9][23]; +int mpeg3_shortLimit[9][14]; + +struct mpeg3_bandInfoStruct mpeg3_bandInfo[9] = +{ + +/* MPEG 1.0 */ + { {0,4,8,12,16,20,24,30,36,44,52,62,74, 90,110,134,162,196,238,288,342,418,576}, + {4,4,4,4,4,4,6,6,8, 8,10,12,16,20,24,28,34,42,50,54, 76,158}, + {0,4*3,8*3,12*3,16*3,22*3,30*3,40*3,52*3,66*3, 84*3,106*3,136*3,192*3}, + {4,4,4,4,6,8,10,12,14,18,22,30,56} } , + + { {0,4,8,12,16,20,24,30,36,42,50,60,72, 88,106,128,156,190,230,276,330,384,576}, + {4,4,4,4,4,4,6,6,6, 8,10,12,16,18,22,28,34,40,46,54, 54,192}, + {0,4*3,8*3,12*3,16*3,22*3,28*3,38*3,50*3,64*3, 80*3,100*3,126*3,192*3}, + {4,4,4,4,6,6,10,12,14,16,20,26,66} } , + + { {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576} , + {4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102, 26} , + {0,4*3,8*3,12*3,16*3,22*3,30*3,42*3,58*3,78*3,104*3,138*3,180*3,192*3} , + {4,4,4,4,6,8,12,16,20,26,34,42,12} } , + +/* MPEG 2.0 */ + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 } , + {0,4*3,8*3,12*3,18*3,24*3,32*3,42*3,56*3,74*3,100*3,132*3,174*3,192*3} , + {4,4,4,6,6,8,10,14,18,26,32,42,18 } } , + + { {0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,330,394,464,540,576}, + {6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,52,64,70,76,36 } , + {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,136*3,180*3,192*3} , + {4,4,4,6,8,10,12,14,18,24,32,44,12 } } , + + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 }, + {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,134*3,174*3,192*3}, + {4,4,4,6,8,10,12,14,18,24,30,40,18 } } , +/* MPEG 2.5 */ + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, + {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, + {4,4,4,6,8,10,12,14,18,24,30,40,18} }, + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, + {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, + {4,4,4,6,8,10,12,14,18,24,30,40,18} }, + { {0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576}, + {12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2}, + {0, 24, 48, 72,108,156,216,288,372,480,486,492,498,576}, + {8,8,8,12,16,20,24,28,36,2,2,2,26} } , +}; + +int mpeg3_mapbuf0[9][152]; +int mpeg3_mapbuf1[9][156]; +int mpeg3_mapbuf2[9][44]; +int *mpeg3_map[9][3]; +int *mpeg3_mapend[9][3]; + +unsigned int mpeg3_n_slen2[512]; /* MPEG 2.0 slen for 'normal' mode */ +unsigned int mpeg3_i_slen2[256]; /* MPEG 2.0 slen for intensity stereo */ + +int mpeg3audio_init_layer3(mpeg3audio_t *audio); + +int mpeg3audio_init_layer2(mpeg3audio_t *audio) +{ + static double mulmul[27] = + { + 0.0 , -2.0/3.0 , 2.0/3.0 , + 2.0/7.0 , 2.0/15.0 , 2.0/31.0, 2.0/63.0 , 2.0/127.0 , 2.0/255.0 , + 2.0/511.0 , 2.0/1023.0 , 2.0/2047.0 , 2.0/4095.0 , 2.0/8191.0 , + 2.0/16383.0 , 2.0/32767.0 , 2.0/65535.0 , + -4.0/5.0 , -2.0/5.0 , 2.0/5.0, 4.0/5.0 , + -8.0/9.0 , -4.0/9.0 , -2.0/9.0 , 2.0/9.0 , 4.0/9.0 , 8.0/9.0 + }; + static int base[3][9] = + { + { 1 , 0, 2 , } , + { 17, 18, 0 , 19, 20 , } , + { 21, 1, 22, 23, 0, 24, 25, 2, 26 } + }; + static int tablen[3] = { 3, 5, 9 }; + static int *itable, *tables[3] = {mpeg3_grp_3tab, mpeg3_grp_5tab, mpeg3_grp_9tab}; + int i, j, k, l, len; + mpeg3_real_t *table; + + for(i = 0; i < 3; i++) + { + itable = tables[i]; + len = tablen[i]; + for(j = 0; j < len; j++) + for(k = 0; k < len; k++) + for(l = 0; l < len; l++) + { + *itable++ = base[i][l]; + *itable++ = base[i][k]; + *itable++ = base[i][j]; + } + } + +#if !defined(USE_FIXED_POINT) || defined(PRINT_FIXED_POINT_TABLES) +#if defined(PRINT_FIXED_POINT_TABLES) + //mpeg3audio_init_layer3(audio); // we depend on mpeg3_muls table +#endif + for(k = 0; k < 27; k++) + { + double m = mulmul[k]; + table = mpeg3_muls[k]; + for(j = 3, i = 0; i < 63; i++, j--) + *table++ = m * pow(2.0, (double)j / 3.0); + *table++ = 0.0; + } +#endif + DO_TABLE2(mpeg3_muls,[64]); + return 0; +} + +int mpeg3audio_init_layer3(mpeg3audio_t *audio) +{ + int i, j, k, l; + int down_sample_sblimit = 32; + + audio->mp3_block[0][0][0] = 0; + audio->mp3_blc[0] = 0; + audio->mp3_blc[1] = 0; + +#if !defined(USE_FIXED_POINT) || defined(PRINT_FIXED_POINT_TABLES) + for(i = -256; i < 118 + 4; i++) + mpeg3_gainpow2[i + 256] = pow((double)2.0, -0.25 * (double)(i + 210)); + + for(i = 0; i < 8207; i++) + mpeg3_ispow[i] = pow((double)i, (double)4.0 / 3.0); + + for(i = 0; i < 8; i++) + { + static double Ci[8] = {-0.6,-0.535,-0.33,-0.185,-0.095,-0.041,-0.0142,-0.0037}; + double sq = sqrt(1.0+Ci[i]*Ci[i]); + mpeg3_aa_cs[i] = 1.0/sq; + mpeg3_aa_ca[i] = Ci[i]/sq; + } + + for(i = 0; i < 18; i++) + { + mpeg3_win[0][i] = mpeg3_win[1][i] = 0.5 * sin( M_PI / 72.0 * (double)(2 * (i + 0) + 1) ) / cos (M_PI * (double)(2 * (i + 0) + 19) / 72.0); + mpeg3_win[0][i+18] = mpeg3_win[3][i+18] = 0.5 * sin( M_PI / 72.0 * (double)(2 * (i + 18) + 1) ) / cos (M_PI * (double)(2 * (i + 18) + 19) / 72.0); + } + for(i = 0; i < 6; i++) + { + mpeg3_win[1][i + 18] = 0.5 / cos ( M_PI * (double) (2*(i+18)+19) / 72.0 ); + mpeg3_win[3][i + 12] = 0.5 / cos ( M_PI * (double) (2*(i+12)+19) / 72.0 ); + mpeg3_win[1][i + 24] = 0.5 * sin( M_PI / 24.0 * (double)(2 * i + 13) ) / cos (M_PI * (double)(2 * (i + 24)+ 19) / 72.0 ); + mpeg3_win[1][i + 30] = mpeg3_win[3][i] = 0.0; + mpeg3_win[3][i + 6 ] = 0.5 * sin( M_PI / 24.0 * (double)(2 * i + 1) ) / cos (M_PI * (double)(2 * (i + 6 )+ 19) / 72.0 ); + } + + for(i = 0; i < 9; i++) + mpeg3_COS9[i] = cos(M_PI / 18.0 * (double)i); + + for(i = 0; i < 9; i++) + mpeg3_tfcos36[i] = 0.5 / cos (M_PI * (double) (i*2+1) / 36.0); + for(i = 0; i < 3; i++) + mpeg3_tfcos12[i] = 0.5 / cos (M_PI * (double) (i*2+1) / 12.0); + + mpeg3_cos9[0] = cos(1.0 * M_PI / 9.0); + mpeg3_cos9[1] = cos(5.0 * M_PI / 9.0); + mpeg3_cos9[2] = cos(7.0 * M_PI / 9.0); + mpeg3_cos18[0] = cos(1.0 * M_PI / 18.0); + mpeg3_cos18[1] = cos(11.0 * M_PI / 18.0); + mpeg3_cos18[2] = cos(13.0 * M_PI / 18.0); + + for(i = 0; i < 12; i++) + { + mpeg3_win[2][i] = 0.5 * sin(M_PI / 24.0 * (double) (2 * i + 1)) / cos(M_PI * (double)(2 * i + 7) / 24.0); + for(j = 0; j < 6; j++) + mpeg3_COS1[i][j] = cos(M_PI / 24.0 * (double) ((2 * i + 7) * (2 * j + 1))); + } + + for(j = 0; j < 4; j++) + { + static int len[4] = {36, 36, 12, 36}; + for(i = 0; i < len[j]; i += 2) + mpeg3_win1[j][i] = + mpeg3_win[j][i]; + for(i = 1; i < len[j]; i += 2) + mpeg3_win1[j][i] = - mpeg3_win[j][i]; + } + + for(i = 0; i < 16; i++) + { + double t = tan( (double) i * M_PI / 12.0 ); + mpeg3_tan1_1[i] = t / (1.0 + t); + mpeg3_tan2_1[i] = 1.0 / (1.0 + t); + mpeg3_tan1_2[i] = M_SQRT2 * t / (1.0 + t); + mpeg3_tan2_2[i] = M_SQRT2 / (1.0 + t); + + for(j = 0; j < 2; j++) + { + double base = pow(2.0, -0.25 * (j + 1.0)); + double p1 = 1.0,p2 = 1.0; + if(i > 0) + { + if( i & 1 ) + p1 = pow(base, (i + 1.0) * 0.5); + else + p2 = pow(base, i * 0.5); + } + mpeg3_pow1_1[j][i] = p1; + mpeg3_pow2_1[j][i] = p2; + mpeg3_pow1_2[j][i] = M_SQRT2 * p1; + mpeg3_pow2_2[j][i] = M_SQRT2 * p2; + } + } + +#endif + + DO_TABLE(mpeg3_gainpow2); + DO_TABLE(mpeg3_ispow); + DO_TABLE(mpeg3_aa_cs); + DO_TABLE(mpeg3_aa_ca); + DO_TABLE2(mpeg3_win,[36]); + DO_TABLE(mpeg3_COS9); + DO_TABLE(mpeg3_tfcos36); + DO_TABLE(mpeg3_tfcos12); + DO_TABLE(mpeg3_cos9); + DO_TABLE(mpeg3_cos18); + DO_TABLE2(mpeg3_COS1,[6]); + DO_TABLE2(mpeg3_win1,[36]); + DO_TABLE(mpeg3_tan1_1); + DO_TABLE(mpeg3_tan2_1); + DO_TABLE(mpeg3_tan1_2); + DO_TABLE(mpeg3_tan2_2); + DO_TABLE2(mpeg3_pow1_1,[16]); + DO_TABLE2(mpeg3_pow2_1,[16]); + DO_TABLE2(mpeg3_pow1_2,[16]); + DO_TABLE2(mpeg3_pow2_2,[16]); + + mpeg3_COS6_1 = cos( M_PI / 6.0 * (double) 1); + mpeg3_COS6_2 = cos( M_PI / 6.0 * (double) 2); + + for(j = 0; j < 9; j++) + { + struct mpeg3_bandInfoStruct *bi = &mpeg3_bandInfo[j]; + int *mp; + int cb,lwin; + int *bdf; + + mp = mpeg3_map[j][0] = mpeg3_mapbuf0[j]; + bdf = bi->longDiff; + for(i = 0, cb = 0; cb < 8; cb++, i += *bdf++) + { + *mp++ = (*bdf) >> 1; + *mp++ = i; + *mp++ = 3; + *mp++ = cb; + } + bdf = bi->shortDiff + 3; + for(cb = 3; cb < 13; cb++) + { + int l = (*bdf++) >> 1; + for(lwin = 0; lwin < 3; lwin++) + { + *mp++ = l; + *mp++ = i + lwin; + *mp++ = lwin; + *mp++ = cb; + } + i += 6 * l; + } + mpeg3_mapend[j][0] = mp; + + mp = mpeg3_map[j][1] = mpeg3_mapbuf1[j]; + bdf = bi->shortDiff+0; + for(i = 0,cb = 0; cb < 13; cb++) + { + int l = (*bdf++) >> 1; + for(lwin = 0; lwin < 3; lwin++) + { + *mp++ = l; + *mp++ = i + lwin; + *mp++ = lwin; + *mp++ = cb; + } + i += 6 * l; + } + mpeg3_mapend[j][1] = mp; + + mp = mpeg3_map[j][2] = mpeg3_mapbuf2[j]; + bdf = bi->longDiff; + for(cb = 0; cb < 22 ; cb++) + { + *mp++ = (*bdf++) >> 1; + *mp++ = cb; + } + mpeg3_mapend[j][2] = mp; + } + + for(j = 0; j < 9; j++) + { + for(i = 0; i < 23; i++) + { + mpeg3_longLimit[j][i] = (mpeg3_bandInfo[j].longIdx[i] - 1 + 8) / 18 + 1; + if(mpeg3_longLimit[j][i] > (down_sample_sblimit)) + mpeg3_longLimit[j][i] = down_sample_sblimit; + } + for(i = 0; i < 14; i++) + { + mpeg3_shortLimit[j][i] = (mpeg3_bandInfo[j].shortIdx[i] - 1) / 18 + 1; + if(mpeg3_shortLimit[j][i] > (down_sample_sblimit) ) + mpeg3_shortLimit[j][i] = down_sample_sblimit; + } + } + + for(i = 0; i < 5; i++) + { + for(j = 0; j < 6; j++) + { + for(k = 0; k < 6; k++) + { + int n = k + j * 6 + i * 36; + mpeg3_i_slen2[n] = i | (j << 3) | (k << 6) | (3 << 12); + } + } + } + for(i = 0; i < 4; i++) + { + for(j = 0; j < 4; j++) + { + for(k = 0; k < 4; k++) + { + int n = k + j * 4 + i * 16; + mpeg3_i_slen2[n+180] = i | (j << 3) | (k << 6) | (4 << 12); + } + } + } + for(i = 0; i < 4; i++) + { + for(j = 0; j < 3; j++) + { + int n = j + i * 3; + mpeg3_i_slen2[n + 244] = i | (j << 3) | (5 << 12); + mpeg3_n_slen2[n + 500] = i | (j << 3) | (2 << 12) | (1 << 15); + } + } + + for(i = 0; i < 5; i++) + { + for(j = 0; j < 5; j++) + { + for(k = 0; k < 4; k++) + { + for(l = 0; l < 4; l++) + { + int n = l + k * 4 + j * 16 + i * 80; + mpeg3_n_slen2[n] = i | (j << 3) | ( k << 6) | (l << 9) | (0 << 12); + } + } + } + } + for(i = 0; i < 5; i++) + { + for(j = 0; j < 5; j++) + { + for(k = 0; k < 4; k++) + { + int n = k + j * 4 + i * 20; + mpeg3_n_slen2[n + 400] = i | (j << 3) | (k << 6) | (1 << 12); + } + } + } + + return 0; +} + +int mpeg3audio_new_decode_tables(mpeg3audio_t *audio) +{ + int i, j, k, kr, divv; + mpeg3_real_t *costab; + int idx; + long scaleval = audio->outscale; + + + for(i = 0; i < 5; i++) + { + kr = 0x10 >> i; + divv = 0x40 >> i; + costab = mpeg3_pnts[i]; + for(k = 0; k < kr; k++) + costab[k] = 1.0 / (2.0 * cos(M_PI * ((double)k * 2.0 + 1.0) / (double)divv)); + +#ifdef USE_3DNOW + for(k = 0; k < kr; k++) + costab[k + kr] = -costab[k]; +#endif + + } + + idx = 0; + scaleval = -scaleval; + for(i = 0, j = 0; i < 256; i++, j++,idx += 32) + { + if(idx < 512 + 16) + mpeg3_decwin[idx+16] = mpeg3_decwin[idx] = (double)mpeg3_intwinbase[j] / 65536.0 * (double)scaleval; + + if(i % 32 == 31) + idx -= 1023; + if(i % 64 == 63) + scaleval = -scaleval; + } + + for( ; i < 512; i++, j--, idx += 32) + { + if(idx < 512 + 16) + mpeg3_decwin[idx + 16] = mpeg3_decwin[idx] = (double)mpeg3_intwinbase[j] / 65536.0 * (double)scaleval; + + if(i % 32 == 31) + idx -= 1023; + if(i % 64 == 63) + scaleval = -scaleval; + } + +#ifdef USE_3DNOW + if(!param.down_sample) + { + for(i = 0; i < 512 + 32; i++) + { + mpeg3_decwin[512 + 31 - i] *= 65536.0; /* allows faster clipping in 3dnow code */ + mpeg3_decwin[512 + 32 + i] = mpeg3_decwin[512 + 31 - i]; + } + } +#endif + +/* Initialize AC3 */ + audio->ac3_lfsr_state = 1; + mpeg3audio_imdct_init(audio); +/* Initialize MPEG */ + mpeg3audio_init_layer2(audio); /* inits also shared tables with layer1 */ + mpeg3audio_init_layer3(audio); + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/audio/tables.h b/core/multimedia/opieplayer/libmpeg3/audio/tables.h new file mode 100644 index 0000000..7b14de1 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/tables.h @@ -0,0 +1,88 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef TABLES_H +#define TABLES_H + +extern int mpeg3_tabsel_123[2][3][16]; + +extern long mpeg3_freqs[9]; + +struct mpeg3_bandInfoStruct +{ + int longIdx[23]; + int longDiff[22]; + int shortIdx[14]; + int shortDiff[13]; +}; + + +extern mpeg3_real_t mpeg3_decwin[512 + 32]; +extern mpeg3_real_t mpeg3_cos64[16], mpeg3_cos32[8], mpeg3_cos16[4], mpeg3_cos8[2], mpeg3_cos4[1]; + +extern mpeg3_real_t *mpeg3_pnts[5]; + +extern int mpeg3_grp_3tab[32 * 3]; /* used: 27 */ +extern int mpeg3_grp_5tab[128 * 3]; /* used: 125 */ +extern int mpeg3_grp_9tab[1024 * 3]; /* used: 729 */ +extern long mpeg3_intwinbase[257]; +extern mpeg3_real_t mpeg3_COS6_1, mpeg3_COS6_2; + +#if defined(USE_FIXED_POINT) && !defined(PRINT_FIXED_POINT_TABLES) +# define REAL_MATRIX(var,dim1,dimn) mpeg3_real_t (*var)dimn +#else +# define REAL_MATRIX(var,dim1,dimn) mpeg3_real_t var dim1 dimn +#endif +extern REAL_MATRIX(mpeg3_muls, [27], [64]); /* also used by layer 1 */ +extern REAL_MATRIX(mpeg3_gainpow2, [256 + 118 + 4], ); +extern REAL_MATRIX(mpeg3_ispow, [8207], ); +extern REAL_MATRIX(mpeg3_aa_ca, [8], ); +extern REAL_MATRIX(mpeg3_aa_cs, [8], ); +extern REAL_MATRIX(mpeg3_win, [4], [36]); +extern REAL_MATRIX(mpeg3_win1, [4], [36]); +extern REAL_MATRIX(mpeg3_COS1, [12], [6]); +extern REAL_MATRIX(mpeg3_COS9, [9], ); +extern REAL_MATRIX(mpeg3_tfcos36, [9], ); +extern REAL_MATRIX(mpeg3_tfcos12, [3], ); +extern REAL_MATRIX(mpeg3_cos9, [3], ); +extern REAL_MATRIX(mpeg3_cos18, [3], ); +extern REAL_MATRIX(mpeg3_tan1_1, [16], ); +extern REAL_MATRIX(mpeg3_tan2_1, [16], ); +extern REAL_MATRIX(mpeg3_tan1_2, [16], ); +extern REAL_MATRIX(mpeg3_tan2_2, [16], ); +extern REAL_MATRIX(mpeg3_pow1_1, [2], [16]); +extern REAL_MATRIX(mpeg3_pow2_1, [2], [16]); +extern REAL_MATRIX(mpeg3_pow1_2, [2], [16]); +extern REAL_MATRIX(mpeg3_pow2_2, [2], [16]); + +extern int mpeg3_longLimit[9][23]; +extern int mpeg3_shortLimit[9][14]; + +extern struct mpeg3_bandInfoStruct mpeg3_bandInfo[9]; + +extern int mpeg3_mapbuf0[9][152]; +extern int mpeg3_mapbuf1[9][156]; +extern int mpeg3_mapbuf2[9][44]; +extern int *mpeg3_map[9][3]; +extern int *mpeg3_mapend[9][3]; + +extern unsigned int mpeg3_n_slen2[512]; /* MPEG 2.0 slen for 'normal' mode */ +extern unsigned int mpeg3_i_slen2[256]; /* MPEG 2.0 slen for intensity stereo */ + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/audio/uncouple.c b/core/multimedia/opieplayer/libmpeg3/audio/uncouple.c new file mode 100644 index 0000000..d87a078 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/audio/uncouple.c @@ -0,0 +1,135 @@ +/* + * + * uncouple.c Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of libmpeg3 + * + * libmpeg3 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. + * + * libmpeg3 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. + * + */ + +#include "../bitstream.h" +#include "mpeg3audio.h" + +static unsigned char mpeg3_first_bit_lut[256] = +{ + 0, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +/* Converts an unsigned exponent in the range of 0-24 and a 16 bit mantissa + * to an IEEE single precision floating point value */ +static inline void mpeg3audio_ac3_convert_to_float(unsigned short exp, + unsigned short mantissa, + unsigned MPEG3_INT32 *dest) +{ + int num; + short exponent; + int i; + +/* If the mantissa is zero we can simply return zero */ + if(mantissa == 0) + { + *dest = 0; + return; + } + +/* Exponent is offset by 127 in IEEE format minus the shift to + * align the mantissa to 1.f (subtracted in the final result) */ + exponent = 127 - exp; + +/* Take care of the one asymmetric negative number */ + if(mantissa == 0x8000) + mantissa++; + +/* Extract the sign bit, invert the mantissa if it's negative, and + shift out the sign bit */ + if(mantissa & 0x8000) + { + mantissa *= -1; + num = 0x80000000 + (exponent << 23); + } + else + { + mantissa *= 1; + num = exponent << 23; + } + +/* Find the index of the most significant one bit */ + i = mpeg3_first_bit_lut[mantissa >> 8]; + + if(i == 0) + i = mpeg3_first_bit_lut[mantissa & 0xff] + 8; + + *dest = num - (i << 23) + (mantissa << (7 + i)); + return; +} + + +int mpeg3audio_ac3_uncouple(mpeg3audio_t *audio, + mpeg3_ac3bsi_t *bsi, + mpeg3_ac3audblk_t *audblk, + mpeg3_stream_coeffs_t *coeffs) +{ + int i, j; + + for(i = 0; i < bsi->nfchans; i++) + { + for(j = 0; j < audblk->endmant[i]; j++) + mpeg3audio_ac3_convert_to_float(audblk->fbw_exp[i][j], + audblk->chmant[i][j], + (unsigned MPEG3_INT32*)&coeffs->fbw[i][j]); + } + + if(audblk->cplinu) + { + for(i = 0; i < bsi->nfchans; i++) + { + if(audblk->chincpl[i]) + { + mpeg3audio_ac3_uncouple_channel(audio, + coeffs, + audblk, + i); + } + } + + } + + if(bsi->lfeon) + { +/* There are always 7 mantissas for lfe */ + for(j = 0; j < 7 ; j++) + mpeg3audio_ac3_convert_to_float(audblk->lfe_exp[j], + audblk->lfemant[j], + (unsigned MPEG3_INT32*)&coeffs->lfe[j]); + + } + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/bitstream.c b/core/multimedia/opieplayer/libmpeg3/bitstream.c new file mode 100644 index 0000000..b4f46e3 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/bitstream.c @@ -0,0 +1,167 @@ +#include "mpeg3private.h" +#include "mpeg3protos.h" + +#include + +mpeg3_bits_t* mpeg3bits_new_stream(mpeg3_t *file, mpeg3_demuxer_t *demuxer) +{ + mpeg3_bits_t *stream = (mpeg3_bits_t*)malloc(sizeof(mpeg3_bits_t)); + stream->bfr = 0; + stream->bfr_size = 0; + stream->bit_number = 0; + stream->file = file; + stream->demuxer = demuxer; + stream->input_ptr = 0; + return stream; +} + +int mpeg3bits_delete_stream(mpeg3_bits_t* stream) +{ + free(stream); + return 0; +} + + +/* Fill a buffer. Only works if bit_number is on an 8 bit boundary */ +int mpeg3bits_read_buffer(mpeg3_bits_t* stream, unsigned char *buffer, int bytes) +{ + int result, i = 0; + while(stream->bit_number > 0) + { + stream->bit_number -= 8; + mpeg3demux_read_prev_char(stream->demuxer); + } + + stream->bit_number = 0; + stream->bfr_size = 0; + stream->bfr = 0; + result = mpeg3demux_read_data(stream->demuxer, buffer, bytes); + return result; +} + +/* For mp3 decompression use a pointer in a buffer for getbits. */ +int mpeg3bits_use_ptr(mpeg3_bits_t* stream, unsigned char *buffer) +{ + stream->bfr_size = stream->bit_number = 0; + stream->bfr = 0; + stream->input_ptr = buffer; + return 0; +} + +/* Go back to using the demuxer for getbits in mp3. */ +int mpeg3bits_use_demuxer(mpeg3_bits_t* stream) +{ + if(stream->input_ptr) + { + stream->bfr_size = stream->bit_number = 0; + stream->input_ptr = 0; + stream->bfr = 0; + } + + return 0; +} + +/* Reconfigure for reverse operation */ +/* Default is forward operation */ +void mpeg3bits_start_reverse(mpeg3_bits_t* stream) +{ + int i; + for(i = 0; i < stream->bfr_size; i += 8) + if(stream->input_ptr) + stream->input_ptr--; + else + mpeg3demux_read_prev_char(stream->demuxer); +} + +/* Reconfigure for forward operation */ +void mpeg3bits_start_forward(mpeg3_bits_t* stream) +{ + int i; + for(i = 0; i < stream->bfr_size; i += 8) + if(stream->input_ptr) + stream->input_ptr++; + else + mpeg3demux_read_char(stream->demuxer); +} + +/* Erase the buffer with the next 4 bytes in the file. */ +int mpeg3bits_refill(mpeg3_bits_t* stream) +{ + stream->bit_number = 32; + stream->bfr_size = 32; + + if(stream->input_ptr) + { + stream->bfr = (unsigned int)(*stream->input_ptr++) << 24; + stream->bfr |= (unsigned int)(*stream->input_ptr++) << 16; + stream->bfr |= (unsigned int)(*stream->input_ptr++) << 8; + stream->bfr |= *stream->input_ptr++; + } + else + { + stream->bfr = mpeg3demux_read_char(stream->demuxer) << 24; + stream->bfr |= mpeg3demux_read_char(stream->demuxer) << 16; + stream->bfr |= mpeg3demux_read_char(stream->demuxer) << 8; + stream->bfr |= mpeg3demux_read_char(stream->demuxer); + } + return mpeg3demux_eof(stream->demuxer); +} + +/* Erase the buffer with the previous 4 bytes in the file. */ +int mpeg3bits_refill_backwards(mpeg3_bits_t* stream) +{ + stream->bit_number = 0; + stream->bfr_size = 32; + stream->bfr = mpeg3demux_read_prev_char(stream->demuxer); + stream->bfr |= (unsigned int)mpeg3demux_read_prev_char(stream->demuxer) << 8; + stream->bfr |= (unsigned int)mpeg3demux_read_prev_char(stream->demuxer) << 16; + stream->bfr |= (unsigned int)mpeg3demux_read_prev_char(stream->demuxer) << 24; + return mpeg3demux_eof(stream->demuxer); +} + +int mpeg3bits_byte_align(mpeg3_bits_t *stream) +{ + stream->bit_number = (stream->bit_number + 7) & 0xf8; + return 0; +} + +int mpeg3bits_seek_end(mpeg3_bits_t* stream) +{ + stream->bfr_size = stream->bit_number = 0; + return mpeg3demux_seek_byte(stream->demuxer, mpeg3demuxer_total_bytes(stream->demuxer)); +} + +int mpeg3bits_seek_start(mpeg3_bits_t* stream) +{ + stream->bfr_size = stream->bit_number = 0; + return mpeg3demux_seek_byte(stream->demuxer, 0); +} + +int mpeg3bits_seek_time(mpeg3_bits_t* stream, double time_position) +{ + stream->bfr_size = stream->bit_number = 0; + return mpeg3demux_seek_time(stream->demuxer, time_position); +} + +int mpeg3bits_seek_byte(mpeg3_bits_t* stream, long position) +{ + stream->bfr_size = stream->bit_number = 0; + return mpeg3demux_seek_byte(stream->demuxer, position); +} + +int mpeg3bits_seek_percentage(mpeg3_bits_t* stream, double percentage) +{ + stream->bfr_size = stream->bit_number = 0; + return mpeg3demux_seek_percentage(stream->demuxer, percentage); +} + +int mpeg3bits_tell(mpeg3_bits_t* stream) +{ + return mpeg3demux_tell(stream->demuxer); +} + +int mpeg3bits_getbitoffset(mpeg3_bits_t *stream) +{ + return stream->bit_number & 7; +} + diff --git a/core/multimedia/opieplayer/libmpeg3/bitstream.h b/core/multimedia/opieplayer/libmpeg3/bitstream.h new file mode 100644 index 0000000..2f6dcf9 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/bitstream.h @@ -0,0 +1,207 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef BITSTREAM_H +#define BITSTREAM_H + +#include "mpeg3demux.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// next bit in forward direction +// next bit in reverse direction | +// v v +// | | | | | | | | | | | | | | | | | | | | | | | | | | |1|1|1|1|1|1| */ +// ^ ^ +// | bit_number = 1 +// bfr_size = 6 + +typedef struct +{ + unsigned MPEG3_INT32 bfr; /* bfr = buffer for bits */ + int bit_number; /* position of pointer in bfr */ + int bfr_size; /* number of bits in bfr. Should always be a multiple of 8 */ + struct mpeg3_rec *file; /* Mpeg2 file */ + mpeg3_demuxer_t *demuxer; /* Mpeg2 demuxer */ +/* If the input ptr is true, data is read from it instead of the demuxer. */ + unsigned char *input_ptr; +} mpeg3_bits_t; + +LIBMPEG_EXPORT unsigned int mpeg3demux_read_char_packet(mpeg3_demuxer_t *demuxer); +LIBMPEG_EXPORT unsigned int mpeg3demux_read_prev_char_packet(mpeg3_demuxer_t *demuxer); + +/* ======================================================================== */ +/* Entry Points */ +/* ======================================================================== */ + +#define mpeg3bits_tell_percentage(stream) mpeg3demux_tell_percentage((stream)->demuxer) + +#define mpeg3bits_packet_time(stream) mpeg3demux_current_time((stream)->demuxer) + +#define mpeg3bits_time_offset(stream) mepg2demux_time_offset((stream)->demuxer) + +#define mpeg3bits_error(stream) mpeg3demux_error((stream)->demuxer) + +#define mpeg3bits_eof(stream) mpeg3demux_eof((stream)->demuxer) + +#define mpeg3bits_bof(stream) mpeg3demux_bof((stream)->demuxer) + +/* Read bytes backward from the file until the reverse_bits is full. */ +static inline void mpeg3bits_fill_reverse_bits(mpeg3_bits_t* stream, int bits) +{ +// Right justify + while(stream->bit_number > 7) + { + stream->bfr >>= 8; + stream->bfr_size -= 8; + stream->bit_number -= 8; + } + +// Insert bytes before bfr_size + while(stream->bfr_size - stream->bit_number < bits) + { + if(stream->input_ptr) + stream->bfr |= (unsigned int)(*--stream->input_ptr) << stream->bfr_size; + else + stream->bfr |= (unsigned int)mpeg3demux_read_prev_char(stream->demuxer) << stream->bfr_size; + stream->bfr_size += 8; + } +} + +/* Read bytes forward from the file until the forward_bits is full. */ +extern inline void mpeg3bits_fill_bits(mpeg3_bits_t* stream, int bits) +{ + while(stream->bit_number < bits) + { + stream->bfr <<= 8; + if(stream->input_ptr) + { + stream->bfr |= *stream->input_ptr++; + } + else + { + stream->bfr |= mpeg3demux_read_char(stream->demuxer); + } + stream->bit_number += 8; + stream->bfr_size += 8; + if(stream->bfr_size > 32) stream->bfr_size = 32; + } +} + +/* Return 8 bits, advancing the file position. */ +extern inline unsigned int mpeg3bits_getbyte_noptr(mpeg3_bits_t* stream) +{ + if(stream->bit_number < 8) + { + stream->bfr <<= 8; + if(stream->input_ptr) + stream->bfr |= *stream->input_ptr++; + else + stream->bfr |= mpeg3demux_read_char(stream->demuxer); + + stream->bfr_size += 8; + if(stream->bfr_size > 32) stream->bfr_size = 32; + + return (stream->bfr >> stream->bit_number) & 0xff; + } + return (stream->bfr >> (stream->bit_number -= 8)) & 0xff; +} + +extern inline unsigned int mpeg3bits_getbit_noptr(mpeg3_bits_t* stream) +{ + if(!stream->bit_number) + { + stream->bfr <<= 8; + stream->bfr |= mpeg3demux_read_char(stream->demuxer); + + stream->bfr_size += 8; + if(stream->bfr_size > 32) stream->bfr_size = 32; + + stream->bit_number = 7; + + return (stream->bfr >> 7) & 0x1; + } + return (stream->bfr >> (--stream->bit_number)) & (0x1); +} + +/* Return n number of bits, advancing the file position. */ +/* Use in place of flushbits */ +extern inline unsigned int mpeg3bits_getbits(mpeg3_bits_t* stream, int bits) +{ + if(bits <= 0) return 0; + mpeg3bits_fill_bits(stream, bits); + return (stream->bfr >> (stream->bit_number -= bits)) & (0xffffffff >> (32 - bits)); +} + +extern inline unsigned int mpeg3bits_showbits24_noptr(mpeg3_bits_t* stream) +{ + while(stream->bit_number < 24) + { + stream->bfr <<= 8; + stream->bfr |= mpeg3demux_read_char(stream->demuxer); + stream->bit_number += 8; + stream->bfr_size += 8; + if(stream->bfr_size > 32) stream->bfr_size = 32; + } + return (stream->bfr >> (stream->bit_number - 24)) & 0xffffff; +} + +extern inline unsigned int mpeg3bits_showbits32_noptr(mpeg3_bits_t* stream) +{ + while(stream->bit_number < 32) + { + stream->bfr <<= 8; + stream->bfr |= mpeg3demux_read_char(stream->demuxer); + stream->bit_number += 8; + stream->bfr_size += 8; + if(stream->bfr_size > 32) stream->bfr_size = 32; + } + return stream->bfr; +} + +extern inline unsigned int mpeg3bits_showbits(mpeg3_bits_t* stream, int bits) +{ + mpeg3bits_fill_bits(stream, bits); + return (stream->bfr >> (stream->bit_number - bits)) & (0xffffffff >> (32 - bits)); +} + +extern inline unsigned int mpeg3bits_getbits_reverse(mpeg3_bits_t* stream, int bits) +{ + unsigned int result; + mpeg3bits_fill_reverse_bits(stream, bits); + result = (stream->bfr >> stream->bit_number) & (0xffffffff >> (32 - bits)); + stream->bit_number += bits; + return result; +} + +extern inline unsigned int mpeg3bits_showbits_reverse(mpeg3_bits_t* stream, int bits) +{ + unsigned int result; + mpeg3bits_fill_reverse_bits(stream, bits); + result = (stream->bfr >> stream->bit_number) & (0xffffffff >> (32 - bits)); + return result; +} + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/c_flags b/core/multimedia/opieplayer/libmpeg3/c_flags new file mode 100755 index 0000000..0c8a75d --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/c_flags @@ -0,0 +1,4 @@ +case "$1" in + *.c) echo $CFLAGS_lessopt +;; *) echo $CFLAGS +esac diff --git a/core/multimedia/opieplayer/libmpeg3/configure b/core/multimedia/opieplayer/libmpeg3/configure new file mode 100755 index 0000000..e75af76 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/configure @@ -0,0 +1,102 @@ +#!/bin/sh + +USE_MMX=1 +USE_CSS=1 +LESS_OPT= +PLATFORM_CFLAGS="-malign-loops=2 -malign-jumps=2 -malign-functions=2 -march=i486" +DEBUG= +OPTIMIZE=-O2 +OPTIMIZE_less=-O +DEFINES= +CC=gcc + +for ac_option +do +case "$ac_option" in + --fixed-point) + CC=g++ + DEFINES="$DEFINES -DUSE_FIXED_POINT" + ;; + + --lessopt) + LESS_OPT=1 + ;; + + --no-mmx) + USE_MMX=0 + ;; + + --no-css) + USE_CSS=0 + ;; + + --debug) + DEBUG=-g + ;; + + --gcc-prefix=*) + CROSS=${ac_option#--gcc-prefix=} + PLATFORM_CFLAGS="" + ;; + -h | --help | -help) + cat << EOF +Options: + --no-mmx Compile libmpeg3 with no MMX support. + --no-css Compile libmpeg3 with no CSS support. + --fixed-point Compile libmpeg3 to use integers instead of floats. + --debug Compile libmpeg3 with debug support. +EOF + exit 0 + ;; + + *) + ;; +esac +done + + +echo "Configuring libmpeg3" + +cat > global_config << EOF +# DO NOT EDIT. EDIT ./configure INSTEAD AND RERUN IT. +EOF + + +if test -z "$CFLAGS"; then + CF="$DEFINES $DEBUG -funroll-loops -fomit-frame-pointer $PLATFORM_CFLAGS" + echo >> global_config "CFLAGS = $CF $OPTIMIZE" + if test -z "$LESS_OPT"; then + echo >> global_config "CFLAGS_lessopt = $CF $OPTIMIZE_less" + else + echo >> global_config "CFLAGS_lessopt = $CF $OPTIMIZE_less" + fi +fi + +cat >> global_config << EOF +CC = ${CROSS}$CC +AR = ${CROSS}ar +NASM = nasm +EOF + +if [ ${USE_CSS} = 1 ]; then +cat >> global_config << EOF +CFLAGS += -DHAVE_CSS +EOF +fi + +if [ ${USE_MMX} = 1 ]; then +cat >> global_config << EOF +CFLAGS += -DHAVE_MMX +MMXOBJS = \ + video/mmxidct.o \ + video/reconmmx.o +MMXOBJS2 = \ + mmxidct.o \ + reconmmx.o +EOF +fi + + + + +echo "done" diff --git a/core/multimedia/opieplayer/libmpeg3/docs/index.html b/core/multimedia/opieplayer/libmpeg3/docs/index.html new file mode 100644 index 0000000..2d79978 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/docs/index.html @@ -0,0 +1,306 @@ +LibMPEG3 + +

+Using LibMPEG3 to make your own MPEG applications

+ + + + + +
+ +Author: Adam Williams broadcast@earthling.net
+Homepage: heroinewarrior.com
+
+
+

+ +

+ + +LibMPEG3 decodes the many many derivatives of MPEG standards into +uncompressed data suitable for editing and playback.

+ +libmpeg3 currently decodes:

+ +

MPEG-2 video
+MPEG-1 video
+mp3 audio
+mp2 audio
+ac3 audio
+MPEG-2 system streams
+MPEG-1 system streams +

+ +The video output can be in many different color models and frame +sizes. The audio output can be in twos compliment or floating +point.

+ + + + + + + + + +STEP 1: Verifying file compatibility

+ +Programs using libmpeg3 must #include "libmpeg3.h".

+ +Call mpeg3_check_sig to verify if the file can be read by +libmpeg3. This returns a 1 if it is compatible and 0 if it isn't.

+ + + + + + + + + + + +STEP 2: Open the file

+ +You need an mpeg3_t* file descriptor:

+ +mpeg3_t* file; + +

+ +Then you need to open the file:

+ +file = mpeg3_open(char *path);

+ +mpeg3_open returns a NULL if the file couldn't be opened +for some reason. Be sure to check this. Everything you do with +libmpeg3 requires passing the file pointer.

+ + + + + + + + + + + + + + +STEP 3: How many CPUs do you want to use?

+ +Call mpeg3_set_cpus(mpeg3_t *file, int cpus) to set how +many CPUs should be devoted to video decompression. LibMPEG3 can use +any number. If you don't call this right after opening the file, the +CPU number defaults to 1.

+ + + + + + + +STEP 4: Get some information about the file.

+ +There are a number of queries for the audio components of the stream:

+ +

+int mpeg3_has_audio(mpeg3_t *file);
+int mpeg3_total_astreams(mpeg3_t *file);             // Number of multiplexed audio streams
+int mpeg3_audio_channels(mpeg3_t *file, int stream);
+int mpeg3_sample_rate(mpeg3_t *file, int stream);
+long mpeg3_audio_samples(mpeg3_t *file, int stream); // Total length
+
+ +The audio is presented as a number of streams starting at 0 and +including mpeg3_total_astreams - 1. Each stream contains a +certain number of channels starting at 0 and including +mpeg3_audio_channels - 1. + +The methodology is first determine if the file has audio, then get +the number of streams in the file, then for each stream get the number +of channels, sample rate, and length.

+ +There are also queries for the video components:

+ +

+int mpeg3_has_video(mpeg3_t *file);
+int mpeg3_total_vstreams(mpeg3_t *file);            // Number of multiplexed video streams
+int mpeg3_video_width(mpeg3_t *file, int stream);
+int mpeg3_video_height(mpeg3_t *file, int stream);
+float mpeg3_frame_rate(mpeg3_t *file, int stream);  // Frames/sec
+long mpeg3_video_frames(mpeg3_t *file, int stream); // Total length
+
+ +The video behavior is the same as with audio, except that video has no +subdivision under streams. Frame rate is a floating point +number of frames per second.

+ + + + + + + +STEP 5: Seeking to a point in the file

+ +Each audio stream and each video stream has a position in the file +independant of each other stream. A variety of methods are available +for specifying the position of a stream: percentage, frame, sample. +Which method you use depends on whether you're seeking audio or video +and whether you're seeking all tracks to a percentage of the file.

+ +The preferred seeking method if you're writing a player is:

+ +

+int mpeg3_seek_percentage(mpeg3_t *file, double percentage);
+double mpeg3_tell_percentage(mpeg3_t *file);
+
+ +This seeks all tracks to a percentage of the file length. The +percentage is from 0 to 1.

+ +The alternative is absolute seeking. The audio seeking is handled +by:

+ +

+int mpeg3_set_sample(mpeg3_t *file, long sample, int stream);    // Seek
+long mpeg3_get_sample(mpeg3_t *file, int stream);    // Tell current position
+
+ +and the video seeking is handled by:

+ +

+int mpeg3_set_frame(mpeg3_t *file, long frame, int stream); // Seek
+long mpeg3_get_frame(mpeg3_t *file, int stream);            // Tell current position
+
+ + +You can either perform percentage seeking or absolute seeking but not +both on the same file handle. Once you perform either method, the file +becomes configured for that method.

+ +If you're in percentage seeking mode and you want the current time +stamp in the file you can't use mpeg3_tell_percentage because you don't +know how many seconds the total length is. The +mpeg3_audio_samples and mpeg3_video_frames +commands don't work in percentage seeking. Instead use + +

+double mpeg3_get_time(mpeg3_t *file);
+
+ +which gives you the last timecode read in seconds. The MPEG standard +specifies timecodes being placed in the streams.

+ + + + + + + + + + + +STEP 6: Read the data

+ +To read audio data use:

+ +

+int mpeg3_read_audio(mpeg3_t *file, 
+		float *output_f,      // Pointer to pre-allocated buffer of floats
+		short *output_i,      // Pointer to pre-allocated buffer if int16's
+		int channel,          // Channel to decode
+		long samples,         // Number of samples to decode
+		int stream);          // Stream containing the channel
+
+ +This decodes a buffer of sequential floats or int16's for a single +channel, depending on which *output... parameter has a nonzero +argument. To get a floating point buffer pass a pre-allocated buffer +to output_f and NULL to output_i. To get an +int16 buffer pass NULL to output_f and a pre-allocated +buffer to output_i.

+ +After reading an audio buffer, the current position in the one stream +is advanced. How then, do you read more than one channel of audio +data? Use + +

+mpeg3_reread_audio(mpeg3_t *file, 
+		float *output_f,      /* Pointer to pre-allocated buffer of floats */
+		short *output_i,      /* Pointer to pre-allocated buffer of int16's */
+		int channel,          /* Channel to decode */
+		long samples,         /* Number of samples to decode */
+		int stream);
+
+ +to read each remaining channel after the first channel.

+ +To read video data there are two methods. RGB frames or YUV +frames. To get an RGB frame use:
+ +

+int mpeg3_read_frame(mpeg3_t *file, 
+		unsigned char **output_rows, // Array of pointers to the start of each output row
+		int in_x,                    // Location in input frame to take picture
+		int in_y, 
+		int in_w, 
+		int in_h, 
+		int out_w,                   // Dimensions of output_rows
+		int out_h, 
+		int color_model,             // One of the color model #defines given above.
+		int stream);
+
+ +The video decoding works like a camcorder taking copy of a movie +screen. The decoder "sees" a region of the movie screen defined by +in_x, in_y, in_w, in_h and transfers it to the frame +buffer defined by **output_rows. The input values must be +within the boundaries given by mpeg3_video_width and +mpeg3_video_height. The size of the frame buffer is +defined by out_w, out_h. Although the input dimensions +are constrained, the frame buffer can be any size.

+ +color_model defines which RGB color model the picture +should be decoded to and the possible values are given in +libmpeg3.h. The frame buffer pointed to by +output_rows must have enough memory allocated to store the +color model you select.

+ +You must allocate 4 extra bytes in the last output_row. This is +scratch area for the MMX routines.

+ +mpeg3_read_frame advances the position in the one stream by 1 frame.

+ +The alternative is YUV frames:
+ +

+int mpeg3_read_yuvframe(mpeg3_t *file,
+		char *y_output,
+		char *u_output,
+		char *v_output,
+		int in_x,
+		int in_y,
+		int in_w,
+		int in_h,
+		int stream);
+
+ +The behavior of in_x, in_y, in_w, in_h is identical to mpeg3_read_frame +except here you have no control over the output frame size. You +must allocate in_w * in_h for the y_output, and in_w * in_h / 4 for the +chroma outputs.

+ + + + + +STEP 7: Close the file

+ +Be sure to close the file with mpeg3_close(mpeg3_t *file) +when you're done with it. diff --git a/core/multimedia/opieplayer/libmpeg3/dump.c b/core/multimedia/opieplayer/libmpeg3/dump.c new file mode 100644 index 0000000..7158712 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/dump.c @@ -0,0 +1,79 @@ +#include "libmpeg3.h" +#include + +#define BUFSIZE 4096 + +int main(int argc, char *argv[]) +{ + mpeg3_t *file; + int i, result = 0; + unsigned char *output, **output_rows; + float *audio_output_f; + short *audio_output_i; + long total_samples = 0; + + if(argc < 2) + { + printf("Need an MPEG stream.\n"); + exit(1); + } + + file = mpeg3_open(argv[1]); + if(file) + { + fprintf(stderr, "MMX supported %d\n", file->have_mmx); + fprintf(stderr, "Audio streams: %d\n", mpeg3_total_astreams(file)); + for(i = 0; i < mpeg3_total_astreams(file); i++) + { + fprintf(stderr, " Stream %d: channels %d sample rate %d total samples %ld\n", + i, + mpeg3_audio_channels(file, i), + mpeg3_sample_rate(file, i), + mpeg3_audio_samples(file, i)); + } + fprintf(stderr, "Video streams: %d\n", mpeg3_total_vstreams(file)); + for(i = 0; i < mpeg3_total_vstreams(file); i++) + { + fprintf(stderr, " Stream %d: width %d height %d frame rate %0.3f total frames %ld\n", + i, + mpeg3_video_width(file, i), + mpeg3_video_height(file, i), + mpeg3_frame_rate(file, i), + mpeg3_video_frames(file, i)); + } +fprintf(stderr,"S"); + + mpeg3_set_cpus(file, 1); +fprintf(stderr,"s"); +/* audio_output_f = malloc(BUFSIZE * sizeof(float)); */ + audio_output_i = (short*)malloc(BUFSIZE * 2 * sizeof(short)); +fprintf(stderr,"x"); +/* mpeg3_set_sample(file, 11229518, 0); */ + /*result = mpeg3_read_audio(file, audio_output_f, 0, 0, BUFSIZE, 0);*/ + for (i=0; i<100; i++) { +fprintf(stderr,"c"); + result = mpeg3_read_audio(file, 0, audio_output_i, 0, BUFSIZE, 0); +fprintf(stderr,"read\n"); + } + //fwrite(audio_output_i, BUFSIZE, 1, stdout); + + output = (unsigned char*)malloc(mpeg3_video_width(file, 0) * mpeg3_video_height(file, 0) * 3 + 4); + output_rows = (unsigned char**)malloc(sizeof(unsigned char*) * mpeg3_video_height(file, 0)); + for(i = 0; i < mpeg3_video_height(file, 0); i++) + output_rows[i] = &output[i * mpeg3_video_width(file, 0) * 3]; +// mpeg3_set_frame(file, 1000, 0); + result = mpeg3_read_frame(file, + output_rows, + 0, + 0, + mpeg3_video_width(file, 0), + mpeg3_video_height(file, 0), + mpeg3_video_width(file, 0), + mpeg3_video_height(file, 0), + MPEG3_RGB888, + 0); + + mpeg3_close(file); + } + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/libmpeg3.c b/core/multimedia/opieplayer/libmpeg3/libmpeg3.c new file mode 100644 index 0000000..c0fc570 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/libmpeg3.c @@ -0,0 +1,672 @@ +#include "libmpeg3.h" +#include "mpeg3protos.h" + +#include +#include + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +mpeg3_t* mpeg3_new(char *path) +{ + int i; + mpeg3_t *file = (mpeg3_t*)calloc(1, sizeof(mpeg3_t)); + file->cpus = 1; + file->fs = mpeg3_new_fs(path); + file->have_mmx = mpeg3_mmx_test(); + file->demuxer = mpeg3_new_demuxer(file, 0, 0, -1); + return file; +} + +int mpeg3_delete(mpeg3_t *file) +{ + int i; + + for(i = 0; i < file->total_vstreams; i++) + mpeg3_delete_vtrack(file, file->vtrack[i]); + + for(i = 0; i < file->total_astreams; i++) + mpeg3_delete_atrack(file, file->atrack[i]); + + mpeg3_delete_fs(file->fs); + mpeg3_delete_demuxer(file->demuxer); + free(file); +} + +int mpeg3_check_sig(char *path) +{ + mpeg3_fs_t *fs; + unsigned int bits; + char *ext; + int result = 0; + + fs = mpeg3_new_fs(path); + if(mpeg3io_open_file(fs)) + { +/* File not found */ + return 0; + } + + bits = mpeg3io_read_int32(fs); +/* Test header */ + if(bits == MPEG3_TOC_PREFIX || bits == MPEG3_TOC_PREFIXLOWER) + { + result = 1; + } + else + if((((bits >> 24) & 0xff) == MPEG3_SYNC_BYTE) || + (bits == MPEG3_PACK_START_CODE) || + ((bits & 0xfff00000) == 0xfff00000) || + (bits == MPEG3_SEQUENCE_START_CODE) || + (bits == MPEG3_PICTURE_START_CODE) || + (((bits & 0xffff0000) >> 16) == MPEG3_AC3_START_CODE) || + ((bits >> 8) == MPEG3_ID3_PREFIX) || + (bits == MPEG3_RIFF_CODE)) + { + result = 1; + + ext = strrchr(path, '.'); + if(ext) + { +/* Test file extension. */ + if(strncasecmp(ext, ".mp2", 4) && + strncasecmp(ext, ".mp3", 4) && + strncasecmp(ext, ".m1v", 4) && + strncasecmp(ext, ".m2v", 4) && + strncasecmp(ext, ".m2s", 4) && + strncasecmp(ext, ".mpg", 4) && + strncasecmp(ext, ".vob", 4) && + strncasecmp(ext, ".mpeg", 4) && + strncasecmp(ext, ".ac3", 4)) + result = 0; + } + } + + mpeg3io_close_file(fs); + mpeg3_delete_fs(fs); + return result; +} + +mpeg3_t* mpeg3_open_copy(char *path, mpeg3_t *old_file) +{ + mpeg3_t *file = 0; + unsigned int bits; + int i, done; + +/* Initialize the file structure */ + file = mpeg3_new(path); + +/* Need to perform authentication before reading a single byte. */ + if(mpeg3io_open_file(file->fs)) + { + mpeg3_delete(file); + return 0; + } + +/* =============================== Create the title objects ========================= */ + bits = mpeg3io_read_int32(file->fs); + + if(bits == MPEG3_TOC_PREFIX || bits == MPEG3_TOC_PREFIXLOWER) /* TOCV */ + { +/* Table of contents for another file */ + if(mpeg3_read_toc(file)) + { + mpeg3_delete(file); + return 0; + } + mpeg3io_close_file(file->fs); + } + else + if(((bits >> 24) & 0xff) == MPEG3_SYNC_BYTE) + { +/* Transport stream */ + file->packet_size = MPEG3_TS_PACKET_SIZE; + file->is_transport_stream = 1; + } + else + if(bits == MPEG3_PACK_START_CODE) + { +/* Program stream */ + file->packet_size = MPEG3_DVD_PACKET_SIZE; + file->is_program_stream = 1; + } + else + if((bits & 0xfff00000) == 0xfff00000 || + ((bits >> 8) == MPEG3_ID3_PREFIX) || + (bits == MPEG3_RIFF_CODE)) + { +/* MPEG Audio only */ + file->packet_size = MPEG3_DVD_PACKET_SIZE; + file->has_audio = 1; + file->is_audio_stream = 1; + } + else + if(bits == MPEG3_SEQUENCE_START_CODE || + bits == MPEG3_PICTURE_START_CODE) + { +/* Video only */ + file->packet_size = MPEG3_DVD_PACKET_SIZE; + file->is_video_stream = 1; + } + else + if(((bits & 0xffff0000) >> 16) == MPEG3_AC3_START_CODE) + { +/* AC3 Audio only */ + file->packet_size = MPEG3_DVD_PACKET_SIZE; + file->has_audio = 1; + file->is_audio_stream = 1; + } + else + { +/* file->packet_size = MPEG3_DVD_PACKET_SIZE; */ +/* file->is_audio_stream = 1; */ + mpeg3_delete(file); + fprintf(stderr, "mpeg3_open: not an MPEG 2 stream\n"); + return 0; + } + +/* Create title */ +/* Copy timecodes from an old demuxer */ + if(old_file && mpeg3_get_demuxer(old_file)) + { + mpeg3demux_copy_titles(file->demuxer, mpeg3_get_demuxer(old_file)); + } + else +/* Start from scratch */ + if(!file->demuxer->total_titles) + { + mpeg3demux_create_title(file->demuxer, 0, 0); + } + +/* =============================== Get title information ========================= */ + if(file->is_transport_stream || file->is_program_stream) + { +/* Create video tracks */ +/* Video must be created before audio because audio uses the video timecode */ +/* to get its length. */ + for(i = 0; i < MPEG3_MAX_STREAMS; i++) + { + if(file->demuxer->vstream_table[i]) + { + file->vtrack[file->total_vstreams] = mpeg3_new_vtrack(file, i, file->demuxer); + if(file->vtrack[file->total_vstreams]) file->total_vstreams++; + } + } + +/* Create audio tracks */ + for(i = 0; i < MPEG3_MAX_STREAMS; i++) + { + if(file->demuxer->astream_table[i]) + { + file->atrack[file->total_astreams] = mpeg3_new_atrack(file, + i, + file->demuxer->astream_table[i], + file->demuxer); + if(file->atrack[file->total_astreams]) file->total_astreams++; + } + } + } + else + if(file->is_video_stream) + { +/* Create video tracks */ + file->vtrack[0] = mpeg3_new_vtrack(file, -1, file->demuxer); + if(file->vtrack[0]) file->total_vstreams++; + } + else + if(file->is_audio_stream) + { +/* Create audio tracks */ + file->atrack[0] = mpeg3_new_atrack(file, -1, AUDIO_UNKNOWN, file->demuxer); + if(file->atrack[0]) file->total_astreams++; + } + + if(file->total_vstreams) file->has_video = 1; + if(file->total_astreams) file->has_audio = 1; + + mpeg3io_close_file(file->fs); + return file; +} + +mpeg3_t* mpeg3_open(char *path) +{ + return mpeg3_open_copy(path, 0); +} + +int mpeg3_close(mpeg3_t *file) +{ +/* File is closed in the same procedure it is opened in. */ + mpeg3_delete(file); + return 0; +} + +int mpeg3_set_cpus(mpeg3_t *file, int cpus) +{ + int i; + file->cpus = cpus; + for(i = 0; i < file->total_vstreams; i++) + mpeg3video_set_cpus(file->vtrack[i]->video, cpus); + return 0; +} + +int mpeg3_set_mmx(mpeg3_t *file, int use_mmx) +{ + int i; + file->have_mmx = use_mmx; + for(i = 0; i < file->total_vstreams; i++) + mpeg3video_set_mmx(file->vtrack[i]->video, use_mmx); + return 0; +} + +int mpeg3_generate_toc(FILE *output, char *path, int timecode_search, int print_streams) +{ + mpeg3_t *file = mpeg3_open(path); + mpeg3_demuxer_t *demuxer; + int i; + + if(file) + { + fprintf(output, "TOCVERSION 2\n" + "PATH: %s\n", path); + demuxer = mpeg3_new_demuxer(file, 0, 0, -1); + mpeg3demux_create_title(demuxer, timecode_search, output); +/* Just print the first title's streams */ + if(print_streams) mpeg3demux_print_streams(demuxer, output); + + fprintf(output, "SIZE: %ld\n", demuxer->titles[demuxer->current_title]->total_bytes); + fprintf(output, "PACKETSIZE: %ld\n", demuxer->packet_size); + + mpeg3demux_print_timecodes(demuxer->titles[demuxer->current_title], output); + + mpeg3_delete_demuxer(demuxer); + mpeg3_close(file); + return 0; + } + return 1; +} + +int mpeg3_read_toc(mpeg3_t *file) +{ + char string[MPEG3_STRLEN]; + int number1; + +/* Test version number */ + file->is_program_stream = 1; + mpeg3io_seek(file->fs, 0); + fscanf(file->fs->fd, "%s %d", string, &number1); + if(number1 > 2 || number1 < 2) return 1; + +/* Read titles */ + mpeg3demux_read_titles(file->demuxer); + return 0; +} + +int mpeg3_has_audio(mpeg3_t *file) +{ + return file->has_audio; +} + +int mpeg3_total_astreams(mpeg3_t *file) +{ + return file->total_astreams; +} + +int mpeg3_audio_channels(mpeg3_t *file, + int stream) +{ + if(file->has_audio) + return file->atrack[stream]->channels; + return -1; +} + +int mpeg3_sample_rate(mpeg3_t *file, + int stream) +{ + if(file->has_audio) + return file->atrack[stream]->sample_rate; + return -1; +} + +long mpeg3_get_sample(mpeg3_t *file, + int stream) +{ + if(file->has_audio) + return file->atrack[stream]->current_position; + return -1; +} + +int mpeg3_set_sample(mpeg3_t *file, + long sample, + int stream) +{ + if(file->has_audio) + { + file->atrack[stream]->current_position = sample; + mpeg3audio_seek_sample(file->atrack[stream]->audio, sample); + return 0; + } + return -1; +} + +long mpeg3_audio_samples(mpeg3_t *file, + int stream) +{ + if(file->has_audio) + return file->atrack[stream]->total_samples; + return -1; +} + +int mpeg3_has_video(mpeg3_t *file) +{ + return file->has_video; +} + +int mpeg3_total_vstreams(mpeg3_t *file) +{ + return file->total_vstreams; +} + +int mpeg3_video_width(mpeg3_t *file, + int stream) +{ + if(file->has_video) + return file->vtrack[stream]->width; + return -1; +} + +int mpeg3_video_height(mpeg3_t *file, + int stream) +{ + if(file->has_video) + return file->vtrack[stream]->height; + return -1; +} + +float mpeg3_frame_rate(mpeg3_t *file, + int stream) +{ + if(file->has_video) + return file->vtrack[stream]->frame_rate; + return -1; +} + +long mpeg3_video_frames(mpeg3_t *file, + int stream) +{ + if(file->has_video) + return file->vtrack[stream]->total_frames; + return -1; +} + +long mpeg3_get_frame(mpeg3_t *file, + int stream) +{ + if(file->has_video) + return file->vtrack[stream]->current_position; + return -1; +} + +int mpeg3_set_frame(mpeg3_t *file, + long frame, + int stream) +{ + if(file->has_video) + { + file->vtrack[stream]->current_position = frame; + mpeg3video_seek_frame(file->vtrack[stream]->video, frame); + return 0; + } + return -1; +} + +int mpeg3_seek_percentage(mpeg3_t *file, double percentage) +{ + int i; + for(i = 0; i < file->total_astreams; i++) + { + mpeg3audio_seek_percentage(file->atrack[i]->audio, percentage); + } + + for(i = 0; i < file->total_vstreams; i++) + { + mpeg3video_seek_percentage(file->vtrack[i]->video, percentage); + } + return 0; +} + +int mpeg3_previous_frame(mpeg3_t *file, int stream) +{ + file->last_type_read = 2; + file->last_stream_read = stream; + + if(file->has_video) + return mpeg3video_previous_frame(file->vtrack[stream]->video); +} + +double mpeg3_tell_percentage(mpeg3_t *file) +{ + double percent = 0; + if(file->last_type_read == 1) + { + percent = mpeg3demux_tell_percentage(file->atrack[file->last_stream_read]->demuxer); + } + + if(file->last_type_read == 2) + { + percent = mpeg3demux_tell_percentage(file->vtrack[file->last_stream_read]->demuxer); + } + return percent; +} + +double mpeg3_get_time(mpeg3_t *file) +{ + double atime = 0, vtime = 0; + + if(file->is_transport_stream || file->is_program_stream) + { +/* Timecode only available in transport stream */ + if(file->last_type_read == 1) + { + atime = mpeg3demux_get_time(file->atrack[file->last_stream_read]->demuxer); + } + else + if(file->last_type_read == 2) + { + vtime = mpeg3demux_get_time(file->vtrack[file->last_stream_read]->demuxer); + } + } + else + { +/* Use percentage and total time */ + if(file->has_audio) + { + atime = mpeg3demux_tell_percentage(file->atrack[0]->demuxer) * + mpeg3_audio_samples(file, 0) / mpeg3_sample_rate(file, 0); + } + + if(file->has_video) + { + vtime = mpeg3demux_tell_percentage(file->vtrack[0]->demuxer) * + mpeg3_video_frames(file, 0) / mpeg3_frame_rate(file, 0); + } + } + + return MAX(atime, vtime); +} + +int mpeg3_end_of_audio(mpeg3_t *file, int stream) +{ + int result = 0; + result = mpeg3demux_eof(file->atrack[stream]->demuxer); + return result; +} + +int mpeg3_end_of_video(mpeg3_t *file, int stream) +{ + int result = 0; + result = mpeg3demux_eof(file->vtrack[stream]->demuxer); + return result; +} + + +int mpeg3_read_frame(mpeg3_t *file, + unsigned char **output_rows, + int in_x, + int in_y, + int in_w, + int in_h, + int out_w, + int out_h, + int color_model, + int stream) +{ + int result = -1; + + if(file->has_video) + { + result = mpeg3video_read_frame(file->vtrack[stream]->video, + file->vtrack[stream]->current_position, + output_rows, + in_x, + in_y, + in_w, + in_h, + out_w, + out_h, + color_model); + file->last_type_read = 2; + file->last_stream_read = stream; + file->vtrack[stream]->current_position++; + } + return result; +} + +int mpeg3_drop_frames(mpeg3_t *file, long frames, int stream) +{ + int result = -1; + + if(file->has_video) + { + result = mpeg3video_drop_frames(file->vtrack[stream]->video, + frames); + if(frames > 0) file->vtrack[stream]->current_position += frames; + file->last_type_read = 2; + file->last_stream_read = stream; + } + return result; +} + +int mpeg3_read_yuvframe(mpeg3_t *file, + char *y_output, + char *u_output, + char *v_output, + int in_x, + int in_y, + int in_w, + int in_h, + int stream) +{ + int result = -1; + +//printf("mpeg3_read_yuvframe 1 %d %d\n", mpeg3demux_tell(file->vtrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->vtrack[stream]->demuxer)); + if(file->has_video) + { + result = mpeg3video_read_yuvframe(file->vtrack[stream]->video, + file->vtrack[stream]->current_position, + y_output, + u_output, + v_output, + in_x, + in_y, + in_w, + in_h); + file->last_type_read = 2; + file->last_stream_read = stream; + file->vtrack[stream]->current_position++; + } +//printf("mpeg3_read_yuvframe 2 %d %d\n", mpeg3demux_tell(file->vtrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->vtrack[stream]->demuxer)); + return result; +} + + +int mpeg3_read_audio(mpeg3_t *file, + mpeg3_real_t *output_f, + short *output_i, int sampleSpacing, + int channel, + long samples, + int stream) +{ + int result = -1; + +//printf("mpeg3_read_audio 1 %d %d\n", mpeg3demux_tell(file->atrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->atrack[stream]->demuxer)); + if(file->has_audio) + { + result = mpeg3audio_decode_audio(file->atrack[stream]->audio, + output_f, + output_i, sampleSpacing, + channel, + file->atrack[stream]->current_position, + samples); + file->last_type_read = 1; + file->last_stream_read = stream; + file->atrack[stream]->current_position += samples; + } +//printf("mpeg3_read_audio 2 %d %d\n", mpeg3demux_tell(file->atrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->atrack[stream]->demuxer)); + + return result; +} + +int mpeg3_reread_audio(mpeg3_t *file, + mpeg3_real_t *output_f, + short *output_i, int sampleSpacing, + int channel, + long samples, + int stream) +{ + if(file->has_audio) + { + mpeg3_set_sample(file, + file->atrack[stream]->current_position - samples, + stream); + file->last_type_read = 1; + file->last_stream_read = stream; + return mpeg3_read_audio(file, + output_f, + output_i, sampleSpacing, + channel, + samples, + stream); + } + return -1; +} + +int mpeg3_read_audio_chunk(mpeg3_t *file, + unsigned char *output, + long *size, + long max_size, + int stream) +{ + int result = 0; + if(file->has_audio) + { + result = mpeg3audio_read_raw(file->atrack[stream]->audio, output, size, max_size); + file->last_type_read = 1; + file->last_stream_read = stream; + } + return result; +} + +int mpeg3_read_video_chunk(mpeg3_t *file, + unsigned char *output, + long *size, + long max_size, + int stream) +{ + int result = 0; + if(file->has_video) + { + result = mpeg3video_read_raw(file->vtrack[stream]->video, output, size, max_size); + file->last_type_read = 2; + file->last_stream_read = stream; + } + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/libmpeg3.h b/core/multimedia/opieplayer/libmpeg3/libmpeg3.h new file mode 100644 index 0000000..f4eced4 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/libmpeg3.h @@ -0,0 +1,175 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef LIBMPEG3_H +#define LIBMPEG3_H + +#include "mpeg3private.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Supported color models for mpeg3_read_frame */ +#define MPEG3_RGB565 2 +#define MPEG3_BGR888 0 +#define MPEG3_BGRA8888 1 +#define MPEG3_RGB888 3 +#define MPEG3_RGBA8888 4 +#define MPEG3_RGBA16161616 5 + +/* Color models for the 601 to RGB conversion */ +/* 601 not implemented for scalar code */ +#define MPEG3_601_RGB565 11 +#define MPEG3_601_BGR888 7 +#define MPEG3_601_BGRA8888 8 +#define MPEG3_601_RGB888 9 +#define MPEG3_601_RGBA8888 10 + +/* Check for file compatibility. Return 1 if compatible. */ +LIBMPEG_EXPORT int mpeg3_check_sig(char *path); + +/* Open the MPEG3 stream. */ +LIBMPEG_EXPORT mpeg3_t* mpeg3_open(char *path); + +/* Open the MPEG3 stream and copy the tables from an already open stream. */ +/* Eliminates the initial timecode search. */ +LIBMPEG_EXPORT mpeg3_t* mpeg3_open_copy(char *path, mpeg3_t *old_file); +LIBMPEG_EXPORT int mpeg3_close(mpeg3_t *file); + +/* Performance */ +LIBMPEG_EXPORT int mpeg3_set_cpus(mpeg3_t *file, int cpus); +LIBMPEG_EXPORT int mpeg3_set_mmx(mpeg3_t *file, int use_mmx); + +/* Query the MPEG3 stream about audio. */ +LIBMPEG_EXPORT int mpeg3_has_audio(mpeg3_t *file); +LIBMPEG_EXPORT int mpeg3_total_astreams(mpeg3_t *file); /* Number of multiplexed audio streams */ +LIBMPEG_EXPORT int mpeg3_audio_channels(mpeg3_t *file, int stream); +LIBMPEG_EXPORT int mpeg3_sample_rate(mpeg3_t *file, int stream); + +/* Total length obtained from the timecode. */ +/* For DVD files, this is unreliable. */ +LIBMPEG_EXPORT long mpeg3_audio_samples(mpeg3_t *file, int stream); +LIBMPEG_EXPORT int mpeg3_set_sample(mpeg3_t *file, long sample, int stream); /* Seek to a sample */ +LIBMPEG_EXPORT long mpeg3_get_sample(mpeg3_t *file, int stream); /* Tell current position */ + +/* Read a PCM buffer of audio from 1 channel and advance the position. */ +/* Return a 1 if error. */ +/* Stream defines the number of the multiplexed stream to read. */ +LIBMPEG_EXPORT int mpeg3_read_audio(mpeg3_t *file, + mpeg3_real_t *output_f, /* Pointer to pre-allocated buffer of floats */ + short *output_i, /* Pointer to pre-allocated buffer of int16's */ + int sampleSpacing, // how many bytes to skip over inbetween samples + int channel, /* Channel to decode */ + long samples, /* Number of samples to decode */ + int stream); /* Stream containing the channel */ + +/* Reread the last PCM buffer from a different channel and advance the position */ +LIBMPEG_EXPORT int mpeg3_reread_audio(mpeg3_t *file, + mpeg3_real_t *output_f, /* Pointer to pre-allocated buffer of floats */ + short *output_i, /* Pointer to pre-allocated buffer of int16's */ + int sampleSpacing, // how many bytes to skip over inbetween samples + int channel, /* Channel to decode */ + long samples, /* Number of samples to decode */ + int stream); /* Stream containing the channel */ + +/* Read the next compressed audio chunk. Store the size in size and return a */ +/* 1 if error. */ +/* Stream defines the number of the multiplexed stream to read. */ +LIBMPEG_EXPORT int mpeg3_read_audio_chunk(mpeg3_t *file, + unsigned char *output, + long *size, + long max_size, + int stream); + +/* Query the stream about video. */ +LIBMPEG_EXPORT int mpeg3_has_video(mpeg3_t *file); +LIBMPEG_EXPORT int mpeg3_total_vstreams(mpeg3_t *file); /* Number of multiplexed video streams */ +LIBMPEG_EXPORT int mpeg3_video_width(mpeg3_t *file, int stream); +LIBMPEG_EXPORT int mpeg3_video_height(mpeg3_t *file, int stream); +LIBMPEG_EXPORT float mpeg3_frame_rate(mpeg3_t *file, int stream); /* Frames/sec */ + +/* Total length. */ +/* For DVD files, this is 1 indicating only percentage seeking is available. */ +LIBMPEG_EXPORT long mpeg3_video_frames(mpeg3_t *file, int stream); +LIBMPEG_EXPORT int mpeg3_set_frame(mpeg3_t *file, long frame, int stream); /* Seek to a frame */ +LIBMPEG_EXPORT int mpeg3_skip_frames(); +LIBMPEG_EXPORT long mpeg3_get_frame(mpeg3_t *file, int stream); /* Tell current position */ + +/* Seek all the tracks based on a percentage of the total bytes in the */ +/* file or the total */ +/* time in a toc if one exists. Percentage is a 0 to 1 double. */ +/* This eliminates the need for tocs and 64 bit longs but doesn't */ +/* give frame accuracy. */ +LIBMPEG_EXPORT int mpeg3_seek_percentage(mpeg3_t *file, double percentage); +LIBMPEG_EXPORT double mpeg3_tell_percentage(mpeg3_t *file); +LIBMPEG_EXPORT int mpeg3_previous_frame(mpeg3_t *file, int stream); +LIBMPEG_EXPORT int mpeg3_end_of_audio(mpeg3_t *file, int stream); +LIBMPEG_EXPORT int mpeg3_end_of_video(mpeg3_t *file, int stream); + +/* Give the seconds time in the last packet read */ +LIBMPEG_EXPORT double mpeg3_get_time(mpeg3_t *file); + +/* Read a frame. The dimensions of the input area and output frame must be supplied. */ +/* The frame is taken from the input area and scaled to fit the output frame in 1 step. */ +/* Stream defines the number of the multiplexed stream to read. */ +/* The last row of **output_rows must contain 4 extra bytes for scratch work. */ +LIBMPEG_EXPORT int mpeg3_read_frame(mpeg3_t *file, + unsigned char **output_rows, /* Array of pointers to the start of each output row */ + int in_x, /* Location in input frame to take picture */ + int in_y, + int in_w, + int in_h, + int out_w, /* Dimensions of output_rows */ + int out_h, + int color_model, /* One of the color model #defines */ + int stream); + +/* Read a YUV frame. The 3 planes are copied into the y, u, and v buffers provided. */ +/* The input is cropped to the dimensions given but not scaled. */ +LIBMPEG_EXPORT int mpeg3_read_yuvframe(mpeg3_t *file, + char *y_output, + char *u_output, + char *v_output, + int in_x, + int in_y, + int in_w, + int in_h, + int stream); + +LIBMPEG_EXPORT int mpeg3_drop_frames(mpeg3_t *file, long frames, int stream); + +/* Read the next compressed frame including headers. */ +/* Store the size in size and return a 1 if error. */ +/* Stream defines the number of the multiplexed stream to read. */ +LIBMPEG_EXPORT int mpeg3_read_video_chunk(mpeg3_t *file, + unsigned char *output, + long *size, + long max_size, + int stream); + +/* Master control */ +LIBMPEG_EXPORT int mpeg3_total_programs(); +LIBMPEG_EXPORT int mpeg3_set_program(int program); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/libmpeg3.pro b/core/multimedia/opieplayer/libmpeg3/libmpeg3.pro new file mode 100644 index 0000000..e2c35d3 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/libmpeg3.pro @@ -0,0 +1,42 @@ +TEMPLATE = lib +CONFIG += qt warn_on release +HEADERS = libmpeg3plugin.h libmpeg3pluginimpl.h +SOURCES = libmpeg3plugin.cpp libmpeg3pluginimpl.cpp \ + bitstream.c \ + libmpeg3.c \ + mpeg3atrack.c \ + mpeg3css.c \ + mpeg3demux.c \ + mpeg3io.c \ + mpeg3title.c \ + mpeg3vtrack.c \ + audio/ac3.c \ + audio/bit_allocation.c \ + audio/dct.c \ + audio/exponents.c \ + audio/header.c \ + audio/layer2.c \ + audio/layer3.c \ + audio/mantissa.c \ + audio/mpeg3audio.c \ + audio/pcm.c \ + audio/synthesizers.c \ + audio/tables.c \ + video/getpicture.c \ + video/headers.c \ + video/idct.c \ + video/macroblocks.c \ + video/mmxtest.c \ + video/motion.c \ + video/mpeg3video.c \ + video/output.c \ + video/reconstruct.c \ + video/seek.c \ + video/slice.c \ + video/vlc.c +TARGET = mpeg3plugin +DESTDIR = ../../plugins/codecs +INCLUDEPATH += $(QPEDIR)/include .. +DEPENDPATH += ../$(QPEDIR)/include .. +LIBS += -lqpe -lpthread -lm +VERSION = 1.0.0 diff --git a/core/multimedia/opieplayer/libmpeg3/libmpeg3plugin.cpp b/core/multimedia/opieplayer/libmpeg3/libmpeg3plugin.cpp new file mode 100644 index 0000000..044cb4a --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/libmpeg3plugin.cpp @@ -0,0 +1,105 @@ +/********************************************************************** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "libmpeg3plugin.h" + +/* +bool LibMpeg3Plugin::audioReadSamples( short *output, int channel, long samples, int stream ) { + return file ? mpeg3_read_audio( file, 0, output, 0, channel, samples, stream ) == 1 : FALSE; +} + + +bool LibMpeg3Plugin::audioReReadSamples( short *output, int channel, long samples, int stream ) { + return file ? mpeg3_reread_audio( file, 0, output, 0, channel, samples, stream ) == 1 : FALSE; +} + + +bool LibMpeg3Plugin::audioReadMonoSamples( short *output, long samples, long& samplesRead, int stream ) { + samplesRead = samples; + return file ? mpeg3_read_audio( file, 0, output, 0, 0, samples, stream ) == 1 : FALSE; +} + + +bool LibMpeg3Plugin::audioReadStereoSamples( short *output, long samples, long& samplesRead, int stream ) { + bool err = FALSE; + if ( file ) { +#if 1 + err = mpeg3_read_audio ( file, 0, output, 1, 0, samples, stream ) == 1; + if ( err == FALSE ) { + err = mpeg3_reread_audio( file, 0, output + 1, 1, 1, samples, stream ) == 1; +#else + short left[samples]; + short right[samples]; + err = mpeg3_read_audio ( file, 0, left, 0, samples, stream ) == 1; + if ( !err ) + err = mpeg3_reread_audio( file, 0, right, 1, samples, stream ) == 1; + for ( int j = 0; j < samples; j++ ) { + output[j*2+0] = left[j]; + output[j*2+1] = right[j]; +#endif + } + } + samplesRead = samples; + return err; +} +*/ + +bool LibMpeg3Plugin::audioReadSamples( short *output, int channels, long samples, long& samplesRead, int stream ) { + samplesRead = samples; + switch ( channels ) { + case 1: + return file ? mpeg3_read_audio( file, 0, output, 0, 0, samples, stream ) == 1 : FALSE; + case 2: + if ( ( file ) && ( mpeg3_read_audio( file, 0, output, 1, 0, samples, stream ) != 1 ) && + ( mpeg3_reread_audio( file, 0, output + 1, 1, 1, samples, stream ) != 1 ) ) + return TRUE; + return FALSE; + } + return FALSE; +} + +bool LibMpeg3Plugin::videoReadFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, ColorFormat color_model, int stream ) { + int format = MPEG3_RGB565; + switch ( color_model ) { + case RGB565: format = MPEG3_RGB565; break; + case BGR565: /*format = MPEG3_BGR565;*/ break; + case RGBA8888: format = MPEG3_RGBA8888; break; + case BGRA8888: format = MPEG3_BGRA8888; break; + } + return file ? mpeg3_read_frame( file, output_rows, in_x, in_y, in_w, in_h, in_w, in_h, format, stream ) == 1 : FALSE; +} + + +bool LibMpeg3Plugin::videoReadScaledFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, ColorFormat color_model, int stream ) { + int format = MPEG3_RGB565; + switch ( color_model ) { + case RGB565: format = MPEG3_RGB565; break; + case BGR565: /*format = MPEG3_BGR565;*/ break; + case RGBA8888: format = MPEG3_RGBA8888; break; + case BGRA8888: format = MPEG3_BGRA8888; break; + } + return file ? mpeg3_read_frame( file, output_rows, in_x, in_y, in_w, in_h, out_w, out_h, format, stream ) == 1 : FALSE; +} + + +bool LibMpeg3Plugin::videoReadYUVFrame( char *y_output, char *u_output, char *v_output, int in_x, int in_y, int in_w, int in_h, int stream ) { + return file ? mpeg3_read_yuvframe( file, y_output, u_output, v_output, in_x, in_y, in_w, in_h, stream ) == 1 : FALSE; +} + + diff --git a/core/multimedia/opieplayer/libmpeg3/libmpeg3plugin.h b/core/multimedia/opieplayer/libmpeg3/libmpeg3plugin.h new file mode 100644 index 0000000..0a06264 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/libmpeg3plugin.h @@ -0,0 +1,113 @@ +/********************************************************************** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef LIBMPEG3_PLUGIN_H +#define LIBMPEG3_PLUGIN_H + + +#include +#include +#include "libmpeg3.h" +#include "mpeg3protos.h" +#include "mediaplayerplugininterface.h" + + +class LibMpeg3Plugin : public MediaPlayerDecoder { + +public: + LibMpeg3Plugin() { file = NULL; } + ~LibMpeg3Plugin() { close(); } + + const char *pluginName() { return "LibMpeg3Plugin"; } + const char *pluginComment() { return "This is the libmpeg3 library writen by ... which has been modified by trolltech to use fixed point maths"; } + double pluginVersion() { return 1.0; } + + bool isFileSupported( const QString& fileName ) { return mpeg3_check_sig( (char *)fileName.latin1() ) == 1; } + bool open( const QString& fileName ) { file = mpeg3_open( (char *)fileName.latin1() ); return file != NULL; } + bool close() { if ( file ) { int r = mpeg3_close( file ); file = NULL; return r == 1; } return FALSE; } + bool isOpen() { return file != NULL; } + const QString &fileInfo() { return strInfo = QString( "" ); } + + // If decoder doesn't support audio then return 0 here + int audioStreams() { return file ? mpeg3_total_astreams( file ) : 0; } + int audioChannels( int stream ) { return file ? mpeg3_audio_channels( file, stream ) : 0; } + int audioFrequency( int stream ) { return file ? mpeg3_sample_rate( file, stream ) : 0; } + int audioSamples( int stream ) { return file ? mpeg3_audio_samples( file, stream ) : 0; } + bool audioSetSample( long sample, int stream ) { return file ? mpeg3_set_sample( file, sample, stream) == 1 : FALSE; } + long audioGetSample( int stream ) { return file ? mpeg3_get_sample( file, stream ) : 0; } +// bool audioReadMonoSamples( short *output, long samples, long& samplesRead, int stream ); +// bool audioReadStereoSamples( short *output, long samples, long& samplesRead, int stream ); + bool audioReadSamples( short *output, int channels, long samples, long& samplesRead, int stream ); +// bool audioReadSamples( short *output, int channel, long samples, int stream ); +// bool audioReReadSamples( short *output, int channel, long samples, int stream ); + + // If decoder doesn't support video then return 0 here + int videoStreams() { return file ? mpeg3_total_vstreams( file ) : 0; } + int videoWidth( int stream ) { return file ? mpeg3_video_width( file, stream ) : 0; } + int videoHeight( int stream ) { return file ? mpeg3_video_height( file, stream ) : 0; } + double videoFrameRate( int stream ) { return file ? mpeg3_frame_rate( file, stream ) : 0.0; } + int videoFrames( int stream ) +{ return file ? mpeg3_video_frames( file, stream ) : 0; } +/* +{ + if ( file ) { + int frames = mpeg3_video_frames( file, stream ); + if ( frames == 1 ) { + int res = mpeg3_seek_percentage( file, 0.99 ); + printf("res: %i\n", res ); + mpeg3video_seek( file->vtrack[stream]->video ); + frames = mpeg3_get_frame( file, stream ); + mpeg3_seek_percentage( file, 0.0 ); + } + return frames; + } + return 0; +} +*/ + bool videoSetFrame( long frame, int stream ) { return file ? mpeg3_set_frame( file, frame, stream) == 1 : FALSE; } + long videoGetFrame( int stream ) { return file ? mpeg3_get_frame( file, stream ) : 0; } + bool videoReadFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, ColorFormat color_model, int stream ); + bool videoReadScaledFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, ColorFormat color_model, int stream ); + bool videoReadYUVFrame( char *y_output, char *u_output, char *v_output, int in_x, int in_y, int in_w, int in_h, int stream ); + + // Profiling + double getTime() { return file ? mpeg3_get_time( file ) : 0.0; } + + // Ignore if these aren't supported + bool setSMP( int cpus ) { return file ? mpeg3_set_cpus( file, cpus ) == 1 : FALSE; } + bool setMMX( bool useMMX ) { return file ? mpeg3_set_mmx( file, useMMX ) == 1 : FALSE; } + + // Capabilities + bool supportsAudio() { return TRUE; } + bool supportsVideo() { return TRUE; } + bool supportsYUV() { return TRUE; } + bool supportsMMX() { return TRUE; } + bool supportsSMP() { return TRUE; } + bool supportsStereo() { return TRUE; } + bool supportsScaling() { return TRUE; } + +private: + mpeg3_t *file; + QString strInfo; + +}; + + +#endif + diff --git a/core/multimedia/opieplayer/libmpeg3/libmpeg3pluginimpl.cpp b/core/multimedia/opieplayer/libmpeg3/libmpeg3pluginimpl.cpp new file mode 100644 index 0000000..e7216af --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/libmpeg3pluginimpl.cpp @@ -0,0 +1,70 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "libmpeg3plugin.h" +#include "libmpeg3pluginimpl.h" + + +LibMpeg3PluginImpl::LibMpeg3PluginImpl() + : libmpeg3plugin(0), ref(0) +{ +} + + +LibMpeg3PluginImpl::~LibMpeg3PluginImpl() +{ + if ( libmpeg3plugin ) + delete libmpeg3plugin; +} + + +MediaPlayerDecoder *LibMpeg3PluginImpl::decoder() +{ + if ( !libmpeg3plugin ) + libmpeg3plugin = new LibMpeg3Plugin; + return libmpeg3plugin; +} + + +MediaPlayerEncoder *LibMpeg3PluginImpl::encoder() +{ + return NULL; +} + + +#ifndef QT_NO_COMPONENT + + +QRESULT LibMpeg3PluginImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ + *iface = 0; + if ( ( uuid == IID_QUnknown ) || ( uuid == IID_MediaPlayerPlugin ) ) + *iface = this, (*iface)->addRef(); + return QS_OK; +} + + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( LibMpeg3PluginImpl ) +} + + +#endif + diff --git a/core/multimedia/opieplayer/libmpeg3/libmpeg3pluginimpl.h b/core/multimedia/opieplayer/libmpeg3/libmpeg3pluginimpl.h new file mode 100644 index 0000000..29ec6ba --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/libmpeg3pluginimpl.h @@ -0,0 +1,53 @@ +/********************************************************************** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef LIBMPEG3_PLUGIN_IMPL_H +#define LIBMPEG3_PLUGIN_IMPL_H + + +#include "../mediaplayerplugininterface.h" + + +class LibMpeg3Plugin; + + +class LibMpeg3PluginImpl : public MediaPlayerPluginInterface +{ +public: + LibMpeg3PluginImpl(); + virtual ~LibMpeg3PluginImpl(); + +#ifndef QT_NO_COMPONENT + + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT + +#endif + + virtual MediaPlayerDecoder *decoder(); + virtual MediaPlayerEncoder *encoder(); + +private: + LibMpeg3Plugin *libmpeg3plugin; + ulong ref; +}; + + +#endif + diff --git a/core/multimedia/opieplayer/libmpeg3/make_package b/core/multimedia/opieplayer/libmpeg3/make_package new file mode 100755 index 0000000..4be86da --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/make_package @@ -0,0 +1,10 @@ +#!/bin/sh + +VERSION=1.2.1 + +rm -r /tmp/libmpeg3-$VERSION +mkdir -p /tmp/libmpeg3-$VERSION +make clean +cp -rd * /tmp/libmpeg3-$VERSION +cd /tmp +tar zcf libmpeg3-$VERSION.tar.gz libmpeg3-$VERSION diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3atrack.c b/core/multimedia/opieplayer/libmpeg3/mpeg3atrack.c new file mode 100644 index 0000000..e1a900b --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3atrack.c @@ -0,0 +1,36 @@ +#include "libmpeg3.h" +#include "mpeg3protos.h" + +#include + +mpeg3_atrack_t* mpeg3_new_atrack(mpeg3_t *file, int stream_id, int format, mpeg3_demuxer_t *demuxer) +{ + mpeg3_atrack_t *new_atrack; + + new_atrack = (mpeg3_atrack_t*)calloc(1, sizeof(mpeg3_atrack_t)); + new_atrack->channels = 0; + new_atrack->sample_rate = 0; + new_atrack->total_samples = 0; + new_atrack->current_position = 0; + new_atrack->demuxer = mpeg3_new_demuxer(file, 1, 0, stream_id); + if(demuxer) mpeg3demux_copy_titles(new_atrack->demuxer, demuxer); + new_atrack->audio = mpeg3audio_new(file, new_atrack, format); + + if(!new_atrack->audio) + { +/* Failed */ + mpeg3_delete_atrack(file, new_atrack); + new_atrack = 0; + } + return new_atrack; +} + +int mpeg3_delete_atrack(mpeg3_t *file, mpeg3_atrack_t *atrack) +{ + if(atrack->audio) + mpeg3audio_delete(atrack->audio); + if(atrack->demuxer) + mpeg3_delete_demuxer(atrack->demuxer); + free(atrack); +} + diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3atrack.h b/core/multimedia/opieplayer/libmpeg3/mpeg3atrack.h new file mode 100644 index 0000000..9d70640 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3atrack.h @@ -0,0 +1,36 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3ATRACK_H +#define MPEG3ATRACK_H + +#include "mpeg3demux.h" +#include "audio/mpeg3audio.h" + +struct mpeg3_atrack_rec +{ + int channels; + int sample_rate; + mpeg3_demuxer_t *demuxer; + mpeg3audio_t *audio; + long current_position; + long total_samples; +}; + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3cat.c b/core/multimedia/opieplayer/libmpeg3/mpeg3cat.c new file mode 100644 index 0000000..20f7660 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3cat.c @@ -0,0 +1,225 @@ +/* Concatenate elementary streams */ + +#include "libmpeg3.h" + +#include +#include +#include + +#define MPEG3_SEQUENCE_START_CODE 0x000001b3 +#define BUFFER_SIZE 1000000 + +int main(int argc, char *argv[]) +{ + char inpath[1024]; + mpeg3_t *in; + int current_file, current_output_file = 0, i; + unsigned int bits; + unsigned char *buffer; + long output_size; + int result = 0; + long total_frames = 0; + int do_audio = 0, do_video = 0; + int stream = 0; + + if(argc < 2) + { + fprintf(stderr, "Concatenate elementary streams or demultiplex a program stream.\n" + "Usage: mpeg3cat -[av0123456789] [infile...] > \n\n" + "Example: Concatenate 2 video files: mpeg3cat xena1.m2v xena2.m2v > xena.m2v\n" + " Extract audio stream 0: mpeg3cat -a0 xena.vob > war_cry.ac3\n"); + exit(1); + } + + for(i = 1; i < argc; i++) + { + if(argv[i][0] == '-') + { + if(argv[i][1] != 'a' && argv[i][1] != 'v') + { + fprintf(stderr, "invalid option %s\n", argv[i]); + } + else + { + if(argv[i][1] == 'a') do_audio = 1; + else + if(argv[i][1] == 'v') do_video = 1; + + if(argv[i][2] != 0) + { + stream = argv[i][2] - 48; + } + } + } + } + + buffer = (unsigned char*)malloc(BUFFER_SIZE); + + for(current_file = 1; current_file < argc; current_file++) + { + if(argv[current_file][0] == '-') continue; + + strcpy(inpath, argv[current_file]); + if(!(in = mpeg3_open(inpath))) + { + fprintf(stderr, "Skipping %s\n", inpath); + continue; + } + + if((mpeg3_has_audio(in) && in->is_audio_stream) || + (do_audio && !in->is_audio_stream && !in->is_video_stream)) + { + do_audio = 1; +/* Add audio stream to end */ + while(!mpeg3_read_audio_chunk(in, buffer, + &output_size, + BUFFER_SIZE, + stream)) + { + result = !fwrite(buffer, output_size, 1, stdout); + if(result) + { + perror("fwrite audio chunk"); + break; + } + } + } + else + if((mpeg3_has_video(in) && in->is_video_stream) || + (do_video && !in->is_video_stream && !in->is_audio_stream)) + { +/* Add video stream to end */ + int hour, minute, second, frame; + long gop_frame; + unsigned long code; + float carry; + int i, offset; + + do_video = 1; + while(!mpeg3_read_video_chunk(in, + buffer, + &output_size, + BUFFER_SIZE, + stream) && + output_size >= 4) + { + code = (unsigned long)buffer[output_size - 4] << 24; + code |= (unsigned long)buffer[output_size - 3] << 16; + code |= (unsigned long)buffer[output_size - 2] << 8; + code |= (unsigned long)buffer[output_size - 1]; + +/* Got a frame at the end of this buffer. */ + if(code == MPEG3_PICTURE_START_CODE) + { + total_frames++; + } + else + if(code == MPEG3_SEQUENCE_END_CODE) + { +/* Got a sequence end code at the end of this buffer. */ + output_size -= 4; + } + + code = (unsigned long)buffer[0] << 24; + code |= (unsigned long)buffer[1] << 16; + code |= (unsigned long)buffer[2] << 8; + code |= buffer[3]; + + i = 0; + offset = 0; + if(code == MPEG3_SEQUENCE_START_CODE && current_output_file > 0) + { +/* Skip the sequence start code */ + i += 4; + while(i < output_size && + code != MPEG3_GOP_START_CODE) + { + code <<= 8; + code |= buffer[i++]; + } + i -= 4; + offset = i; + } + +/* Search for GOP header to fix */ + code = (unsigned long)buffer[i++] << 24; + code |= (unsigned long)buffer[i++] << 16; + code |= (unsigned long)buffer[i++] << 8; + code |= buffer[i++]; + while(i < output_size && + code != MPEG3_GOP_START_CODE) + { + code <<= 8; + code |= buffer[i++]; + } + + if(code == MPEG3_GOP_START_CODE) + { +/* Get the time code */ + code = (unsigned long)buffer[i] << 24; + code |= (unsigned long)buffer[i + 1] << 16; + code |= (unsigned long)buffer[i + 2] << 8; + code |= (unsigned long)buffer[i + 3]; + + hour = code >> 26 & 0x1f; + minute = code >> 20 & 0x3f; + second = code >> 13 & 0x3f; + frame = code >> 7 & 0x3f; + + gop_frame = (long)(hour * 3600 * mpeg3_frame_rate(in, stream) + + minute * 60 * mpeg3_frame_rate(in, stream) + + second * mpeg3_frame_rate(in, stream) + + frame); +/* fprintf(stderr, "old: %02d:%02d:%02d:%02d ", hour, minute, second, frame); */ +/* Write a new time code */ + hour = (long)((float)(total_frames - 1) / mpeg3_frame_rate(in, stream) / 3600); + carry = hour * 3600 * mpeg3_frame_rate(in, stream); + minute = (long)((float)(total_frames - 1 - carry) / mpeg3_frame_rate(in, stream) / 60); + carry += minute * 60 * mpeg3_frame_rate(in, stream); + second = (long)((float)(total_frames - 1 - carry) / mpeg3_frame_rate(in, stream)); + carry += second * mpeg3_frame_rate(in, stream); + frame = (int)(total_frames - 1 - carry); + + buffer[i] = ((code >> 24) & 0x80) | (hour << 2) | (minute >> 4); + buffer[i + 1] = ((code >> 16) & 0x08) | ((minute & 0xf) << 4) | (second >> 3); + buffer[i + 2] = ((second & 0x7) << 5) | (frame >> 1); + buffer[i + 3] = (code & 0x7f) | ((frame & 0x1) << 7); +/* fprintf(stderr, "new: %02d:%02d:%02d:%02d\n", hour, minute, second, frame); */ + } + +/* Write the frame */ + result = !fwrite(buffer + offset, output_size - offset, 1, stdout); + if(result) + { + perror("fwrite video chunk"); + break; + } + } + } + else + { + fprintf(stderr, "Unsupported stream type.\n"); + mpeg3_close(in); + in = 0; + continue; + } + + mpeg3_close(in); + in = 0; + current_output_file++; + } + +/* Terminate output */ + if(current_output_file > 0 && do_video) + { +/*fprintf(stderr, "\n"); */ +/* Write new end of sequence */ + buffer[0] = MPEG3_SEQUENCE_END_CODE >> 24; + buffer[1] = (MPEG3_SEQUENCE_END_CODE >> 16) & 0xff; + buffer[2] = (MPEG3_SEQUENCE_END_CODE >> 8) & 0xff; + buffer[3] = MPEG3_SEQUENCE_END_CODE & 0xff; + result = !fwrite(buffer, 4, 1, stdout); + } + + exit(0); +} diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3css.c b/core/multimedia/opieplayer/libmpeg3/mpeg3css.c new file mode 100644 index 0000000..7f9ad8c --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3css.c @@ -0,0 +1,32 @@ +#include "mpeg3css.h" +#include "mpeg3private.h" + +extern "C" { + +int mpeg3_init_css(mpeg3_t *file, mpeg3_css_t *css) +{ + return 0; +} + +int mpeg3_get_keys(mpeg3_css_t *css, char *path) +{ + return 1; +} + +int mpeg3_decrypt_packet(mpeg3_css_t *css, unsigned char *sector) +{ + return 1; +} + +mpeg3_css_t* mpeg3_new_css() +{ + return 0; +} + +int mpeg3_delete_css(mpeg3_css_t *css) +{ + return 0; +} + +}; + diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3css.h b/core/multimedia/opieplayer/libmpeg3/mpeg3css.h new file mode 100644 index 0000000..1272574 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3css.h @@ -0,0 +1,29 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3CSS_H +#define MPEG3CSS_H + +/* Stubs for deCSS which can't be distributed legally */ + +typedef struct +{ +} mpeg3_css_t; + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3css_fake.c b/core/multimedia/opieplayer/libmpeg3/mpeg3css_fake.c new file mode 100644 index 0000000..0901195 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3css_fake.c @@ -0,0 +1,19 @@ +/* Stubs for deCSS which can't be distributed in source form */ + +#include "mpeg3css.h" +#include "mpeg3private.h" + +int mpeg3_init_css(mpeg3_t *file, mpeg3_css_t *css) +{ + return 0; +} + +int mpeg3_get_keys(mpeg3_css_t *css, char *path) +{ + return 1; +} + +int mpeg3_decrypt_packet(mpeg3_css_t *css, unsigned char *sector) +{ + return 1; +} diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3css_fake.h b/core/multimedia/opieplayer/libmpeg3/mpeg3css_fake.h new file mode 100644 index 0000000..1272574 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3css_fake.h @@ -0,0 +1,29 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3CSS_H +#define MPEG3CSS_H + +/* Stubs for deCSS which can't be distributed legally */ + +typedef struct +{ +} mpeg3_css_t; + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3demux.c b/core/multimedia/opieplayer/libmpeg3/mpeg3demux.c new file mode 100644 index 0000000..cccc820 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3demux.c @@ -0,0 +1,1849 @@ +#include "libmpeg3.h" +#include "mpeg3io.h" +#include "mpeg3protos.h" + +#include +#include +#include + +#define ABS(x) ((x) >= 0 ? (x) : -(x)) + +/* Don't advance pointer */ +static inline unsigned char mpeg3packet_next_char(mpeg3_demuxer_t *demuxer) +{ + return demuxer->raw_data[demuxer->raw_offset]; +} + +unsigned char mpeg3packet_read_char(mpeg3_demuxer_t *demuxer) +{ + unsigned char result = demuxer->raw_data[demuxer->raw_offset++]; + return result; +} + +static inline unsigned int mpeg3packet_read_int16(mpeg3_demuxer_t *demuxer) +{ + unsigned int a, b, result; + a = demuxer->raw_data[demuxer->raw_offset++]; + b = demuxer->raw_data[demuxer->raw_offset++]; + result = (a << 8) | b; + + return result; +} + +static inline unsigned int mpeg3packet_next_int24(mpeg3_demuxer_t *demuxer) +{ + unsigned int a, b, c, result; + a = demuxer->raw_data[demuxer->raw_offset]; + b = demuxer->raw_data[demuxer->raw_offset + 1]; + c = demuxer->raw_data[demuxer->raw_offset + 2]; + result = (a << 16) | (b << 8) | c; + + return result; +} + +static inline unsigned int mpeg3packet_read_int24(mpeg3_demuxer_t *demuxer) +{ + unsigned int a, b, c, result; + a = demuxer->raw_data[demuxer->raw_offset++]; + b = demuxer->raw_data[demuxer->raw_offset++]; + c = demuxer->raw_data[demuxer->raw_offset++]; + result = (a << 16) | (b << 8) | c; + + return result; +} + +static inline unsigned int mpeg3packet_read_int32(mpeg3_demuxer_t *demuxer) +{ + unsigned int a, b, c, d, result; + a = demuxer->raw_data[demuxer->raw_offset++]; + b = demuxer->raw_data[demuxer->raw_offset++]; + c = demuxer->raw_data[demuxer->raw_offset++]; + d = demuxer->raw_data[demuxer->raw_offset++]; + result = (a << 24) | (b << 16) | (c << 8) | d; + + return result; +} + +static inline unsigned int mpeg3packet_skip(mpeg3_demuxer_t *demuxer, long length) +{ + demuxer->raw_offset += length; + return 0; +} + +int mpeg3_get_adaptation_field(mpeg3_demuxer_t *demuxer) +{ + long length; + int pcr_flag; + + demuxer->adaptation_fields++; +/* get adaptation field length */ + length = mpeg3packet_read_char(demuxer); +/* get first byte */ + pcr_flag = (mpeg3packet_read_char(demuxer) >> 4) & 1; + + if(pcr_flag) + { + unsigned long clk_ref_base = mpeg3packet_read_int32(demuxer); + unsigned int clk_ref_ext = mpeg3packet_read_int16(demuxer); + + if (clk_ref_base > 0x7fffffff) + { /* correct for invalid numbers */ + clk_ref_base = 0; /* ie. longer than 32 bits when multiplied by 2 */ + clk_ref_ext = 0; /* multiplied by 2 corresponds to shift left 1 (<<=1) */ + } + else + { + clk_ref_base <<= 1; /* Create space for bit */ + clk_ref_base |= (clk_ref_ext >> 15); /* Take bit */ + clk_ref_ext &= 0x01ff; /* Only lower 9 bits */ + } + demuxer->time = clk_ref_base + clk_ref_ext / 300; + if(length) mpeg3packet_skip(demuxer, length - 7); + } + else + mpeg3packet_skip(demuxer, length - 1); + + return 0; +} + +int mpeg3_get_program_association_table(mpeg3_demuxer_t *demuxer) +{ + demuxer->program_association_tables++; + demuxer->table_id = mpeg3packet_read_char(demuxer); + demuxer->section_length = mpeg3packet_read_int16(demuxer) & 0xfff; + demuxer->transport_stream_id = mpeg3packet_read_int16(demuxer); + mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); + return 0; +} + +int mpeg3packet_get_data_buffer(mpeg3_demuxer_t *demuxer) +{ + while(demuxer->raw_offset < demuxer->raw_size && demuxer->data_size < demuxer->data_allocated) + { + demuxer->data_buffer[demuxer->data_size++] = demuxer->raw_data[demuxer->raw_offset++]; + } + return 0; +} + +int mpeg3_get_pes_packet_header(mpeg3_demuxer_t *demuxer, unsigned long *pts, unsigned long *dts) +{ + unsigned int pes_header_bytes = 0; + unsigned int pts_dts_flags; + int pes_header_data_length; + +/* drop first 8 bits */ + mpeg3packet_read_char(demuxer); + pts_dts_flags = (mpeg3packet_read_char(demuxer) >> 6) & 0x3; + pes_header_data_length = mpeg3packet_read_char(demuxer); + +/* Get Presentation Time stamps and Decoding Time Stamps */ + if(pts_dts_flags == 2) + { + *pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ + *pts <<= 15; + *pts |= (mpeg3packet_read_int16(demuxer) >> 1); + *pts <<= 15; + *pts |= (mpeg3packet_read_int16(demuxer) >> 1); + pes_header_bytes += 5; + } + else if(pts_dts_flags == 3) + { + *pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ + *pts <<= 15; + *pts |= (mpeg3packet_read_int16(demuxer) >> 1); + *pts <<= 15; + *pts |= (mpeg3packet_read_int16(demuxer) >> 1); + *dts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ + *dts <<= 15; + *dts |= (mpeg3packet_read_int16(demuxer) >> 1); + *dts <<= 15; + *dts |= (mpeg3packet_read_int16(demuxer) >> 1); + pes_header_bytes += 10; + } +/* extract other stuff here! */ + + mpeg3packet_skip(demuxer, pes_header_data_length - pes_header_bytes); + return 0; +} + +int get_unknown_data(mpeg3_demuxer_t *demuxer) +{ + mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); + return 0; +} + +int mpeg3_get_pes_packet_data(mpeg3_demuxer_t *demuxer, unsigned int stream_id) +{ + unsigned long pts = 0, dts = 0; + + if((stream_id >> 4) == 12 || (stream_id >> 4) == 13) + { +/* Just pick the first available stream if no ID is set */ + if(demuxer->astream == -1) + demuxer->astream = (stream_id & 0x0f); + + if((stream_id & 0x0f) == demuxer->astream && demuxer->do_audio) + { + mpeg3_get_pes_packet_header(demuxer, &pts, &dts); + demuxer->pes_audio_time = pts; + demuxer->audio_pid = demuxer->pid; + return mpeg3packet_get_data_buffer(demuxer); + } + } + else + if((stream_id >> 4)==14) + { +/* Just pick the first available stream if no ID is set */ + if(demuxer->vstream == -1) + demuxer->vstream = (stream_id & 0x0f); + + if((stream_id & 0x0f) == demuxer->vstream && demuxer->do_video) + { + mpeg3_get_pes_packet_header(demuxer, &pts, &dts); + demuxer->pes_video_time = pts; + demuxer->video_pid = demuxer->pid; + return mpeg3packet_get_data_buffer(demuxer); + } + } + else + { + return get_unknown_data(demuxer); + } + + mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); + + return 0; +} + +int mpeg3_get_pes_packet(mpeg3_demuxer_t *demuxer) +{ + unsigned int stream_id; + + demuxer->pes_packets++; + stream_id = mpeg3packet_read_char(demuxer); +/* Skip startcode */ + mpeg3packet_read_int24(demuxer); +/* Skip pes packet length */ + mpeg3packet_read_int16(demuxer); + + if(stream_id != MPEG3_PRIVATE_STREAM_2 && stream_id != MPEG3_PADDING_STREAM) + { + return mpeg3_get_pes_packet_data(demuxer, stream_id); + } + else + if(stream_id == MPEG3_PRIVATE_STREAM_2) + { +/* Dump private data! */ + fprintf(stderr, "stream_id == MPEG3_PRIVATE_STREAM_2\n"); + mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); + return 0; + } + else + if(stream_id == MPEG3_PADDING_STREAM) + { + mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); + return 0; + } + else + { + fprintf(stderr, "unknown stream_id in pes packet"); + return 1; + } + return 0; +} + +int mpeg3_get_payload(mpeg3_demuxer_t *demuxer) +{ + if(demuxer->payload_unit_start_indicator) + { + if(demuxer->pid==0) mpeg3_get_program_association_table(demuxer); + else + if(mpeg3packet_next_int24(demuxer) == MPEG3_PACKET_START_CODE_PREFIX) mpeg3_get_pes_packet(demuxer); + else + mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); + } + else + { + if(demuxer->pid == demuxer->audio_pid && demuxer->do_audio) + { + mpeg3packet_get_data_buffer(demuxer); + } + else + if(demuxer->pid == demuxer->video_pid && demuxer->do_video) + { + mpeg3packet_get_data_buffer(demuxer); + } + else + mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); + } + return 0; +} + +/* Read a transport packet */ +int mpeg3_read_transport(mpeg3_demuxer_t *demuxer) +{ + mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; + int result = mpeg3io_read_data(demuxer->raw_data, demuxer->packet_size, title->fs); + unsigned int bits; + int table_entry; + + demuxer->raw_size = demuxer->packet_size; + demuxer->raw_offset = 0; + if(result) + { + perror("mpeg3_read_transport"); + return 1; + } + +/* Sync byte */ + if(mpeg3packet_read_char(demuxer) != MPEG3_SYNC_BYTE) + { + fprintf(stderr, "mpeg3packet_read_char(demuxer) != MPEG3_SYNC_BYTE\n"); + return 1; + } + +/* bits = mpeg3packet_read_int24(demuxer) & 0x0000ffff; */ +/* demuxer->transport_error_indicator = bits >> 15; */ +/* demuxer->payload_unit_start_indicator = (bits >> 14) & 1; */ +/* demuxer->pid = bits & 0x00001fff; */ +/* demuxer->transport_scrambling_control = (mpeg3packet_next_char(demuxer) >> 6) & 0x3; */ +/* demuxer->adaptation_field_control = (mpeg3packet_next_char(demuxer) >> 4) & 0x3; */ +/* demuxer->continuity_counter = (mpeg3packet_read_char(demuxer) & 0xf); */ + + bits = mpeg3packet_read_int24(demuxer) & 0x00ffffff; + demuxer->transport_error_indicator = (bits >> 23) & 0x1; + demuxer->payload_unit_start_indicator = (bits >> 22) & 0x1; + demuxer->pid = (bits >> 8) & 0x00001fff; + demuxer->transport_scrambling_control = (bits >> 6) & 0x3; + demuxer->adaptation_field_control = (bits >> 4) & 0x3; + demuxer->continuity_counter = bits & 0xf; + + if(demuxer->transport_error_indicator) + { + fprintf(stderr, "demuxer->transport_error_indicator\n"); + return 1; + } + + if (demuxer->pid == 0x1fff) + { + demuxer->is_padding = 1; /* padding; just go to next */ + return 0; + } + else + { + demuxer->is_padding = 0; + } + +/* Get pid */ + for(table_entry = 0, result = 0; table_entry < demuxer->total_pids; table_entry++) + { + if(demuxer->pid == demuxer->pid_table[table_entry]) + { + result = 1; + break; + } + } + +/* Not in pid table */ + if(!result) + { + demuxer->pid_table[table_entry] = demuxer->pid; + demuxer->continuity_counters[table_entry] = demuxer->continuity_counter; /* init */ + demuxer->total_pids++; + } + result = 0; + +/* Check counters */ + if(demuxer->pid != MPEG3_PROGRAM_ASSOCIATION_TABLE && + demuxer->pid != MPEG3_CONDITIONAL_ACCESS_TABLE && + (demuxer->adaptation_field_control == 1 || demuxer->adaptation_field_control == 3)) + { + if(demuxer->continuity_counters[table_entry] != demuxer->continuity_counter) + { + fprintf(stderr, "demuxer->continuity_counters[table_entry] != demuxer->continuity_counter\n"); +/* Reset it */ + demuxer->continuity_counters[table_entry] = demuxer->continuity_counter; + } + if(++(demuxer->continuity_counters[table_entry]) > 15) demuxer->continuity_counters[table_entry] = 0; + } + + if(demuxer->adaptation_field_control == 2 || demuxer->adaptation_field_control == 3) + result = mpeg3_get_adaptation_field(demuxer); + + if(demuxer->adaptation_field_control == 1 || demuxer->adaptation_field_control == 3) + result = mpeg3_get_payload(demuxer); + + return result; +} + +int mpeg3_get_system_header(mpeg3_demuxer_t *demuxer) +{ + int length = mpeg3packet_read_int16(demuxer); + mpeg3packet_skip(demuxer, length); + return 0; +} + +unsigned long mpeg3_get_timestamp(mpeg3_demuxer_t *demuxer) +{ + unsigned long timestamp; +/* Only low 4 bits (7==1111) */ + timestamp = (mpeg3packet_read_char(demuxer) >> 1) & 7; + timestamp <<= 15; + timestamp |= (mpeg3packet_read_int16(demuxer) >> 1); + timestamp <<= 15; + timestamp |= (mpeg3packet_read_int16(demuxer) >> 1); + return timestamp; +} + +int mpeg3_get_pack_header(mpeg3_demuxer_t *demuxer, unsigned int *header) +{ + unsigned long i, j; + unsigned long clock_ref, clock_ref_ext; + +/* Get the time code */ + if((mpeg3packet_next_char(demuxer) >> 4) == 2) + { +/* MPEG-1 */ + demuxer->time = (double)mpeg3_get_timestamp(demuxer) / 90000; +/* Skip 3 bytes */ + mpeg3packet_read_int24(demuxer); + } + else + if(mpeg3packet_next_char(demuxer) & 0x40) + { + i = mpeg3packet_read_int32(demuxer); + j = mpeg3packet_read_int16(demuxer); + if(i & 0x40000000 || (i >> 28) == 2) + { + clock_ref = ((i & 0x31000000) << 3); + clock_ref |= ((i & 0x03fff800) << 4); + clock_ref |= ((i & 0x000003ff) << 5); + clock_ref |= ((j & 0xf800) >> 11); + clock_ref_ext = (j >> 1) & 0x1ff; + + demuxer->time = (double)(clock_ref + clock_ref_ext / 300) / 90000; +/* Skip 3 bytes */ + mpeg3packet_read_int24(demuxer); + i = mpeg3packet_read_char(demuxer) & 0x7; + +/* stuffing */ + mpeg3packet_skip(demuxer, i); + } + } + else + { + mpeg3packet_skip(demuxer, 2); + } + + *header = mpeg3packet_read_int32(demuxer); + if(*header == MPEG3_SYSTEM_START_CODE) + { + mpeg3_get_system_header(demuxer); + *header = mpeg3packet_read_int32(demuxer); + } + return 0; +} + +/* Program packet reading core */ +int mpeg3_get_ps_pes_packet(mpeg3_demuxer_t *demuxer, unsigned int *header) +{ + unsigned long pts = 0, dts = 0; + int stream_id; + int pes_packet_length; + int pes_packet_start; + int i; + mpeg3_t *file = demuxer->file; + + stream_id = *header & 0xff; + pes_packet_length = mpeg3packet_read_int16(demuxer); + pes_packet_start = demuxer->raw_offset; + + if(stream_id != MPEG3_PRIVATE_STREAM_2 && + stream_id != MPEG3_PADDING_STREAM) + { + if((mpeg3packet_next_char(demuxer) >> 6) == 0x02) + { +/* Get MPEG-2 packet */ + int pes_header_bytes = 0; + int scrambling = (mpeg3packet_read_char(demuxer) >> 4) & 0x3; + int pts_dts_flags = (mpeg3packet_read_char(demuxer) >> 6) & 0x3; + int pes_header_data_length = mpeg3packet_read_char(demuxer); + + if(scrambling && (demuxer->do_audio || demuxer->do_video)) + { +/* Decrypt it */ + if(mpeg3_decrypt_packet(demuxer->titles[demuxer->current_title]->fs->css, + demuxer->raw_data)) + { + fprintf(stderr, "mpeg3_get_ps_pes_packet: Decryption not available\n"); + return 1; + } + } + +/* Get Presentation and Decoding Time Stamps */ + if(pts_dts_flags == 2) + { + pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ + pts <<= 15; + pts |= (mpeg3packet_read_int16(demuxer) >> 1); + pts <<= 15; + pts |= (mpeg3packet_read_int16(demuxer) >> 1); + pes_header_bytes += 5; + } + else + if(pts_dts_flags == 3) + { + pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ + pts <<= 15; + pts |= (mpeg3packet_read_int16(demuxer) >> 1); + pts <<= 15; + pts |= (mpeg3packet_read_int16(demuxer) >> 1); + dts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ + dts <<= 15; + dts |= (mpeg3packet_read_int16(demuxer) >> 1); + dts <<= 15; + dts |= (mpeg3packet_read_int16(demuxer) >> 1); + pes_header_bytes += 10; + } + +/* Skip unknown */ + mpeg3packet_skip(demuxer, pes_header_data_length - pes_header_bytes); + } + else + { + int pts_dts_flags; +/* Get MPEG-1 packet */ + while(mpeg3packet_next_char(demuxer) == 0xff) + { + mpeg3packet_read_char(demuxer); + } + +/* Skip STD buffer scale */ + if((mpeg3packet_next_char(demuxer) & 0x40) == 0x40) + { + mpeg3packet_skip(demuxer, 2); + } + +/* Decide which timestamps are available */ + pts_dts_flags = mpeg3packet_next_char(demuxer); + + if(pts_dts_flags >= 0x30) + { +/* Get the presentation and decoding time stamp */ + pts = mpeg3_get_timestamp(demuxer); + dts = mpeg3_get_timestamp(demuxer); + } + else + if(pts_dts_flags >= 0x20) + { +/* Get just the presentation time stamp */ + pts = mpeg3_get_timestamp(demuxer); + } + else + if(pts_dts_flags == 0x0f) + { +/* End of timestamps */ + mpeg3packet_read_char(demuxer); + } + else + { + return 1; /* Error */ + } + } + +/* Now extract the payload. */ + if((stream_id >> 4) == 0xc || (stream_id >> 4) == 0xd) + { +/* Audio data */ +/* Take first stream ID if -1 */ + pes_packet_length -= demuxer->raw_offset - pes_packet_start; + if(!demuxer->do_audio && !demuxer->do_video) + demuxer->astream_table[stream_id & 0x0f] = AUDIO_MPEG; + else + if(demuxer->astream == -1) + demuxer->astream = stream_id & 0x0f; + + if((stream_id & 0x0f) == demuxer->astream && demuxer->do_audio) + { + if(pts) demuxer->pes_audio_time = pts; + + memcpy(&demuxer->data_buffer[demuxer->data_size], + &demuxer->raw_data[demuxer->raw_offset], + pes_packet_length); + demuxer->data_size += pes_packet_length; + demuxer->raw_offset += pes_packet_length; + } + else + { + mpeg3packet_skip(demuxer, pes_packet_length); + } + } + else + if((stream_id >> 4) == 0xe) + { +/* Video data */ +/* Take first stream ID if -1 */ + if(!demuxer->do_audio && !demuxer->do_video) + demuxer->vstream_table[stream_id & 0x0f] = 1; + else + if(demuxer->vstream == -1) + demuxer->vstream = stream_id & 0x0f; + + pes_packet_length -= demuxer->raw_offset - pes_packet_start; + if((stream_id & 0x0f) == demuxer->vstream && demuxer->do_video) + { + if(pts) demuxer->pes_video_time = pts; + + memcpy(&demuxer->data_buffer[demuxer->data_size], + &demuxer->raw_data[demuxer->raw_offset], + pes_packet_length); + demuxer->data_size += pes_packet_length; + demuxer->raw_offset += pes_packet_length; + } + else + { + mpeg3packet_skip(demuxer, pes_packet_length); + } + } + else + if(stream_id == 0xbd && demuxer->raw_data[demuxer->raw_offset] != 0xff) + { +/* DVD audio data */ +/* Get the audio format */ + int format; + if((demuxer->raw_data[demuxer->raw_offset] & 0xf0) == 0xa0) + format = AUDIO_PCM; + else + format = AUDIO_AC3; + + stream_id = demuxer->raw_data[demuxer->raw_offset] - 0x80; + +/* Take first stream ID if not building TOC. */ + if(!demuxer->do_audio && !demuxer->do_video) + demuxer->astream_table[stream_id] = format; + else + if(demuxer->astream == -1) + demuxer->astream = stream_id; + + if(stream_id == demuxer->astream && demuxer->do_audio) + { + demuxer->aformat = format; + if(pts) demuxer->pes_audio_time = pts; + mpeg3packet_read_int32(demuxer); + pes_packet_length -= demuxer->raw_offset - pes_packet_start; + + memcpy(&demuxer->data_buffer[demuxer->data_size], + &demuxer->raw_data[demuxer->raw_offset], + pes_packet_length); + demuxer->data_size += pes_packet_length; + demuxer->raw_offset += pes_packet_length; + } + else + { + pes_packet_length -= demuxer->raw_offset - pes_packet_start; + mpeg3packet_skip(demuxer, pes_packet_length); + } + } + else + if(stream_id == 0xbc || 1) + { + pes_packet_length -= demuxer->raw_offset - pes_packet_start; + mpeg3packet_skip(demuxer, pes_packet_length); + } + } + else + if(stream_id == MPEG3_PRIVATE_STREAM_2 || stream_id == MPEG3_PADDING_STREAM) + { + pes_packet_length -= demuxer->raw_offset - pes_packet_start; + mpeg3packet_skip(demuxer, pes_packet_length); + } + + while(demuxer->raw_offset + 4 < demuxer->raw_size) + { + *header = mpeg3packet_read_int32(demuxer); + if((*header >> 8) != MPEG3_PACKET_START_CODE_PREFIX) + demuxer->raw_offset -= 3; + else + break; + } + + return 0; +} + +int mpeg3_read_program(mpeg3_demuxer_t *demuxer) +{ + int result = 0, count = 0; + mpeg3_t *file = demuxer->file; + mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; + unsigned int header; + demuxer->raw_size = demuxer->packet_size; + demuxer->raw_offset = 0; + demuxer->data_size = 0; + +/* Search backward for it. */ + header = mpeg3io_read_int32(title->fs); + result = mpeg3io_eof(title->fs); + + if(!result) result = mpeg3io_seek_relative(title->fs, -4); + +// Search backwards for header + while(header != MPEG3_PACK_START_CODE && !result && count < demuxer->packet_size) + { + result = mpeg3io_seek_relative(title->fs, -1); + if(!result) + { + header >>= 8; + header |= mpeg3io_read_char(title->fs) << 24; + result = mpeg3io_seek_relative(title->fs, -1); + } + count++; + } + + if(result) + { +// couldn't find MPEG3_PACK_START_CODE + return 1; + } + + result = mpeg3io_read_data(demuxer->raw_data, demuxer->packet_size, title->fs); + + if(result) + { + perror("mpeg3_read_program"); + return 1; + } + + header = mpeg3packet_read_int32(demuxer); + while(demuxer->raw_offset + 4 < demuxer->raw_size && !result) + { + if(header == MPEG3_PACK_START_CODE) + { + result = mpeg3_get_pack_header(demuxer, &header); + } + else + if((header >> 8) == MPEG3_PACKET_START_CODE_PREFIX) + { + result = mpeg3_get_ps_pes_packet(demuxer, &header); + } + } + return result; +} + +double mpeg3_lookup_time_offset(mpeg3_demuxer_t *demuxer, long byte) +{ + int i; + mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; + + if(!title->timecode_table_size) return 0; + + for(i = title->timecode_table_size - 1; + i >= 0 && title->timecode_table[i].start_byte > byte; + i--) + ; + if(i < 0) i = 0; + return title->timecode_table[i].absolute_start_time - title->timecode_table[i].start_time; +} + +int mpeg3_advance_timecode(mpeg3_demuxer_t *demuxer, int reverse) +{ + mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; + int result = 0; + int do_seek = 0; + +/* Skip timecode advancing when constructing timecode table */ + if(!title->timecode_table || + !title->timecode_table_size || + demuxer->generating_timecode) return 0; + + if(!reverse) + { +/* Get inside the current timecode */ + if(mpeg3io_tell(title->fs) < title->timecode_table[demuxer->current_timecode].start_byte) + { + mpeg3io_seek(title->fs, title->timecode_table[demuxer->current_timecode].start_byte); + } + +/* Get the next timecode */ + while(!result && + (mpeg3io_tell(title->fs) >= title->timecode_table[demuxer->current_timecode].end_byte || + demuxer->current_program != title->timecode_table[demuxer->current_timecode].program)) + { + +/* + * printf("mpeg3_advance_timecode %d %d %d %d\n", mpeg3io_tell(title->fs), title->timecode_table[demuxer->current_timecode].end_byte, + * demuxer->current_program, title->timecode_table[demuxer->current_timecode].program); + */ + + demuxer->current_timecode++; + if(demuxer->current_timecode >= title->timecode_table_size) + { + demuxer->current_timecode = 0; + if(demuxer->current_title + 1 < demuxer->total_titles) + { + mpeg3demux_open_title(demuxer, demuxer->current_title + 1); + do_seek = 1; + } + else + { + mpeg3io_seek(title->fs, mpeg3io_total_bytes(title->fs)); + result = 1; + } + } + title = demuxer->titles[demuxer->current_title]; + } + + if(!result && do_seek) + { + mpeg3io_seek(title->fs, title->timecode_table[demuxer->current_timecode].start_byte); + } + } + else + { +/* Get the previous timecode */ + while(!result && + (mpeg3io_tell(title->fs) < title->timecode_table[demuxer->current_timecode].start_byte || + demuxer->current_program != title->timecode_table[demuxer->current_timecode].program)) + { +/* + * if(demuxer->do_audio) printf("mpeg3_reverse_timecode %d %d %d %d\n", mpeg3io_tell(title->fs), title->timecode_table[demuxer->current_timecode].end_byte, + * demuxer->current_program, title->timecode_table[demuxer->current_timecode].program); + */ + demuxer->current_timecode--; + if(demuxer->current_timecode < 0) + { + if(demuxer->current_title > 0) + { + mpeg3demux_open_title(demuxer, demuxer->current_title - 1); + title = demuxer->titles[demuxer->current_title]; + demuxer->current_timecode = title->timecode_table_size - 1; + do_seek = 1; + } + else + { + mpeg3io_seek(title->fs, 0); + demuxer->current_timecode = 0; + result = 1; + } + } + } + + if(!result && do_seek) + mpeg3io_seek(title->fs, title->timecode_table[demuxer->current_timecode].start_byte); + } + + return result; +} + +/* Read packet in the forward direction */ +int mpeg3_read_next_packet(mpeg3_demuxer_t *demuxer) +{ + int result = 0; + long current_position; + mpeg3_t *file = demuxer->file; + mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; + demuxer->data_size = 0; + demuxer->data_position = 0; + +/* Flip the file descriptor back to the end of the packet for forward */ +/* reading. */ + if(demuxer->reverse) + { + result = mpeg3io_seek_relative(title->fs, demuxer->packet_size); + demuxer->reverse = 0; + } + +/* Read packets until the output buffer is full */ + if(!result) + { + do + { + result = mpeg3_advance_timecode(demuxer, 0); + + if(!result) + { + demuxer->time_offset = mpeg3_lookup_time_offset(demuxer, mpeg3io_tell(title->fs)); + + if(file->is_transport_stream) + { + result = mpeg3_read_transport(demuxer); + } + else + if(file->is_program_stream) + { + result = mpeg3_read_program(demuxer); + } + else + { +/* Read elementary stream. */ + result = mpeg3io_read_data(demuxer->data_buffer, demuxer->packet_size, title->fs); + if(!result) demuxer->data_size = demuxer->packet_size; + } + } + }while(!result && demuxer->data_size == 0 && (demuxer->do_audio || demuxer->do_video)); + } + + return result; +} + +/* Read the packet right before the packet we're currently on. */ +int mpeg3_read_prev_packet(mpeg3_demuxer_t *demuxer) +{ + int result = 0; + mpeg3_t *file = demuxer->file; + long current_position; + mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; + + demuxer->data_size = 0; + demuxer->data_position = 0; + + do + { +/* Rewind to the start of the packet to be read. */ + result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); + + if(!result) result = mpeg3_advance_timecode(demuxer, 1); + if(!result) demuxer->time_offset = mpeg3_lookup_time_offset(demuxer, mpeg3io_tell(title->fs)); + + if(file->is_transport_stream && !result) + { + result = mpeg3_read_transport(demuxer); + if(!mpeg3io_bof(title->fs)) + /* if(!result) */result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); + } + else + if(file->is_program_stream && !result) + { + + result = mpeg3_read_program(demuxer); + if(!mpeg3io_bof(title->fs)) + /* if(!result) */result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); + } + else + if(!result) + { +/* Elementary stream */ +/* Read the packet forwards and seek back to the start */ + result = mpeg3io_read_data(demuxer->data_buffer, demuxer->packet_size, title->fs); + if(!result) + { + demuxer->data_size = demuxer->packet_size; + result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); + } + } + }while(!result && demuxer->data_size == 0 && (demuxer->do_audio || demuxer->do_video)); + +/* Remember that the file descriptor is at the beginning of the packet just read. */ + demuxer->reverse = 1; + demuxer->error_flag = result; + return result; +} + + +/* Used for audio */ +int mpeg3demux_read_data(mpeg3_demuxer_t *demuxer, + unsigned char *output, + long size) +{ + long i; + int result = 0; + mpeg3_t *file = demuxer->file; + demuxer->error_flag = 0; + + if(demuxer->data_position >= 0) + { +/* Read forwards */ + for(i = 0; i < size && !result; ) + { + int fragment_size = size - i; + if(fragment_size > demuxer->data_size - demuxer->data_position) + fragment_size = demuxer->data_size - demuxer->data_position; + memcpy(output + i, demuxer->data_buffer + demuxer->data_position, fragment_size); + demuxer->data_position += fragment_size; + i += fragment_size; + + if(i < size) + { + result = mpeg3_read_next_packet(demuxer); + } + } + } + else + { +/* Read backwards a full packet. */ +/* Only good for reading less than the size of a full packet, but */ +/* this routine should only be used for searching for previous markers. */ + long current_position = demuxer->data_position; + result = mpeg3_read_prev_packet(demuxer); + if(!result) demuxer->data_position = demuxer->data_size + current_position; + memcpy(output, demuxer->data_buffer + demuxer->data_position, size); + demuxer->data_position += size; + } + + demuxer->error_flag = result; + return result; +} + +unsigned int mpeg3demux_read_char_packet(mpeg3_demuxer_t *demuxer) +{ + demuxer->error_flag = 0; + if(demuxer->data_position >= demuxer->data_size) + demuxer->error_flag = mpeg3_read_next_packet(demuxer); + demuxer->next_char = demuxer->data_buffer[demuxer->data_position++]; + return demuxer->next_char; +} + +unsigned int mpeg3demux_read_prev_char_packet(mpeg3_demuxer_t *demuxer) +{ + demuxer->error_flag = 0; + demuxer->data_position--; + if(demuxer->data_position < 0) + { + demuxer->error_flag = mpeg3_read_prev_packet(demuxer); + if(!demuxer->error_flag) demuxer->data_position = demuxer->data_size - 1; + } + demuxer->next_char = demuxer->data_buffer[demuxer->data_position]; + return demuxer->next_char; +} + +mpeg3demux_timecode_t* mpeg3_append_timecode(mpeg3_demuxer_t *demuxer, + mpeg3_title_t *title, + long prev_byte, + double prev_time, + long next_byte, + double next_time, + int dont_store) +{ + mpeg3demux_timecode_t *new_table; + mpeg3demux_timecode_t *new_timecode, *old_timecode; + long i; + + if(!title->timecode_table || + title->timecode_table_allocation <= title->timecode_table_size) + { + if(title->timecode_table_allocation == 0) + title->timecode_table_allocation = 1; + else + title->timecode_table_allocation *= 2; + + new_table = (mpeg3demux_timecode_t*)calloc(1, sizeof(mpeg3demux_timecode_t) * title->timecode_table_allocation); + if(title->timecode_table) + { + for(i = 0; i < title->timecode_table_size; i++) + { + new_table[i] = title->timecode_table[i]; + } + + free(title->timecode_table); + } + title->timecode_table = new_table; + } + + if(!dont_store) + { + new_timecode = &title->timecode_table[title->timecode_table_size]; + new_timecode->start_byte = next_byte; + new_timecode->start_time = next_time; + new_timecode->absolute_start_time = 0; + + if(title->timecode_table_size > 0) + { + old_timecode = &title->timecode_table[title->timecode_table_size - 1]; + old_timecode->end_byte = prev_byte; + old_timecode->end_time = prev_time; + new_timecode->absolute_start_time = + prev_time - + old_timecode->start_time + + old_timecode->absolute_start_time; + new_timecode->absolute_end_time = next_time; + } + } + + title->timecode_table_size++; + return new_timecode; +} + +mpeg3demux_timecode_t* mpeg3demux_next_timecode(mpeg3_demuxer_t *demuxer, + int *current_title, + int *current_timecode, + int current_program) +{ + int done = 0; + while(!done) + { +/* Increase timecode number */ + if(*current_timecode < demuxer->titles[*current_title]->timecode_table_size - 1) + { + (*current_timecode)++; + if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) + return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); + } + else +/* Increase title number */ + if(*current_title < demuxer->total_titles - 1) + { + (*current_title)++; + (*current_timecode) = 0; + if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) + return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); + } + else +/* End of disk */ + done = 1; + } + return 0; +} + +mpeg3demux_timecode_t* mpeg3demux_prev_timecode(mpeg3_demuxer_t *demuxer, + int *current_title, + int *current_timecode, + int current_program) +{ + int done = 0; + while(!done) + { +/* Increase timecode number */ + if(*current_timecode > 0) + { + (*current_timecode)--; + if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) + return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); + } + else +/* Increase title number */ + if(*current_title > 0) + { + (*current_title)--; + (*current_timecode) = demuxer->titles[*current_title]->timecode_table_size - 1; + if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) + return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); + } + else +/* End of disk */ + done = 1; + + } + return 0; +} + +int mpeg3demux_open_title(mpeg3_demuxer_t *demuxer, int title_number) +{ + mpeg3_title_t *title; + + if(title_number < demuxer->total_titles) + { + if(demuxer->current_title >= 0) + { + mpeg3io_close_file(demuxer->titles[demuxer->current_title]->fs); + demuxer->current_title = -1; + } + + title = demuxer->titles[title_number]; + if(mpeg3io_open_file(title->fs)) + { + demuxer->error_flag = 1; + perror("mpeg3demux_open_title"); + } + else + { + demuxer->current_title = title_number; + } + } + + demuxer->current_timecode = 0; + + return demuxer->error_flag; +} + +/* Assign program numbers to interleaved programs */ +int mpeg3demux_assign_programs(mpeg3_demuxer_t *demuxer) +{ + int current_program = 0; + int current_title = 0, previous_title; + int current_timecode = 0, previous_timecode; + double current_time, current_length; + int done = 0; + int interleaved = 0; + mpeg3demux_timecode_t *timecode1, *timecode2; + double program_times[MPEG3_MAX_STREAMS]; + int total_programs = 1; + int i, j; + int program_exists, last_program_assigned = 0; + int total_timecodes; + mpeg3_title_t **titles = demuxer->titles; + + for(i = 0, total_timecodes = 0; i < demuxer->total_titles; i++) + total_timecodes += demuxer->titles[i]->timecode_table_size; + +// if(total_timecodes < 3) return 0; + +/* + * // Assign programs based on length of contiguous timecode + * timecode1 = demuxer->titles[current_title]->timecode_table; + * while(!done) + * { + * if(!timecode1) done = 1; + * else + * if(timecode1->end_time - timecode1->start_time < MPEG3_PROGRAM_THRESHOLD) + * { + * // Got interleaved section + * interleaved = 1; + * program_times[0] = timecode1->end_time; + * + * while(interleaved && !done) + * { + * timecode2 = mpeg3demux_next_timecode(demuxer, + * ¤t_title, + * ¤t_timecode, + * 0); + * + * if(!timecode2) done = 1; + * else + * { + * // Another segment of interleaved data + * if(timecode2->end_time - timecode2->start_time < MPEG3_PROGRAM_THRESHOLD) + * { + * // Search program times for where the previous instance of the program left off + * for(program_exists = 0, i = 0; + * i < total_programs && !program_exists; + * i++) + * { + * // Got a previous instance of the program + * if(program_times[i] + 0.5 > timecode2->start_time && + * program_times[i] - 0.5 < timecode2->start_time) + * { + * program_times[i] = timecode2->end_time; + * timecode2->program = i; + * program_exists = 1; + * + * // Programs must always start at 0 for an interleaved section + * if(i < last_program_assigned && i != 0) + * { + * // Shift programs in the interleaved section down until they start at 0 + * for(j = 0; j < total_programs - 1; j++) + * program_times[j] = program_times[j + 1]; + * + * for(previous_title = current_title, previous_timecode = current_timecode; + * titles[previous_title]->timecode_table[previous_timecode].program > 0 && + * (previous_title >= 0 || previous_timecode >= 0); ) + * { + * titles[previous_title]->timecode_table[previous_timecode].program--; + * previous_timecode--; + * if(previous_timecode < 0 && previous_title > 0) + * { + * previous_title--; + * previous_timecode = titles[previous_title]->timecode_table_size - 1; + * } + * } + * } + * } + * } + * + * // Didn't get one + * if(!program_exists) + * { + * program_times[total_programs] = timecode2->end_time; + * timecode2->program = total_programs++; + * } + * last_program_assigned = timecode2->program; + * } + * // No more interleaved section + * else + * { + * interleaved = 0; + * // Restart program table from the beginning + * total_programs = 1; + * last_program_assigned = 0; + * timecode1 = mpeg3demux_next_timecode(demuxer, + * ¤t_title, + * ¤t_timecode, + * 0); + * } + * } + * } + * } + * else + * // Get next timecode + * timecode1 = mpeg3demux_next_timecode(demuxer, + * ¤t_title, + * ¤t_timecode, + * 0); + * } + * + * demuxer->total_programs = total_programs; + */ + +/* Assign absolute timecodes in each program. */ + for(current_program = 0; + current_program < total_programs; + current_program++) + { + current_time = 0; + current_title = 0; + current_timecode = -1; + while(timecode1 = mpeg3demux_next_timecode(demuxer, + ¤t_title, + ¤t_timecode, + current_program)) + { + timecode1->absolute_start_time = current_time; + current_time += timecode1->end_time - timecode1->start_time; + timecode1->absolute_end_time = current_time; + } + } +//for(i = 0; i < demuxer->total_titles; i++) mpeg3_dump_title(demuxer->titles[i]); + demuxer->current_program = 0; + return 0; +} + +/* ==================================================================== */ +/* Entry points */ +/* ==================================================================== */ + +mpeg3_demuxer_t* mpeg3_new_demuxer(mpeg3_t *file, int do_audio, int do_video, int stream_id) +{ + mpeg3_demuxer_t *demuxer = (mpeg3_demuxer_t*)calloc(1, sizeof(mpeg3_demuxer_t)); + int i; + +/* The demuxer will change the default packet size for its own use. */ + demuxer->file = file; + demuxer->packet_size = file->packet_size; + demuxer->do_audio = do_audio; + demuxer->do_video = do_video; + +/* Allocate buffer + padding */ + demuxer->raw_data = (unsigned char*)calloc(1, MPEG3_MAX_PACKSIZE); + demuxer->data_buffer = (unsigned char*)calloc(1, MPEG3_MAX_PACKSIZE); + demuxer->data_allocated = MPEG3_MAX_PACKSIZE; +/* System specific variables */ + demuxer->audio_pid = stream_id; + demuxer->video_pid = stream_id; + demuxer->astream = stream_id; + demuxer->vstream = stream_id; + demuxer->current_title = -1; + return demuxer; +} + +int mpeg3_delete_demuxer(mpeg3_demuxer_t *demuxer) +{ + int i; + + if(demuxer->current_title >= 0) + { + mpeg3io_close_file(demuxer->titles[demuxer->current_title]->fs); + } + + for(i = 0; i < demuxer->total_titles; i++) + { + mpeg3_delete_title(demuxer->titles[i]); + } + + if(demuxer->data_buffer) free(demuxer->data_buffer); + free(demuxer->raw_data); + free(demuxer); +} + +/* Create a title. */ +/* Build a table of timecodes contained in the program stream. */ +/* If toc is 0 just read the first and last timecode. */ +int mpeg3demux_create_title(mpeg3_demuxer_t *demuxer, int timecode_search, FILE *toc) +{ + int result = 0, done = 0, counter_start, counter; + mpeg3_t *file = demuxer->file; + long next_byte, prev_byte; + double next_time, prev_time, absolute_time; + long i; + mpeg3_title_t *title; + unsigned long test_header = 0; + mpeg3demux_timecode_t *timecode = 0; + + demuxer->error_flag = 0; + demuxer->generating_timecode = 1; + +/* Create a single title */ + if(!demuxer->total_titles) + { + demuxer->titles[0] = mpeg3_new_title(file, file->fs->path); + demuxer->total_titles = 1; + mpeg3demux_open_title(demuxer, 0); + } + title = demuxer->titles[0]; + title->total_bytes = mpeg3io_total_bytes(title->fs); + + +/* Get the packet size from the file */ + if(file->is_program_stream) + { + mpeg3io_seek(title->fs, 4); + for(i = 0; i < MPEG3_MAX_PACKSIZE && + test_header != MPEG3_PACK_START_CODE; i++) + { + test_header <<= 8; + test_header |= mpeg3io_read_char(title->fs); + } + if(i < MPEG3_MAX_PACKSIZE) demuxer->packet_size = i; + mpeg3io_seek(title->fs, 0); + } + else + demuxer->packet_size = file->packet_size; + +/* Get timecodes for the title */ + if(file->is_transport_stream || file->is_program_stream) + { + mpeg3io_seek(title->fs, 0); + while(!done && !result && !mpeg3io_eof(title->fs)) + { + next_byte = mpeg3io_tell(title->fs); + result = mpeg3_read_next_packet(demuxer); + + if(!result) + { + next_time = demuxer->time; +//printf("%f %f\n", next_time, prev_time); + if(next_time < prev_time || + next_time - prev_time > MPEG3_CONTIGUOUS_THRESHOLD || + !title->timecode_table_size) + { +/* Discontinuous */ + timecode = mpeg3_append_timecode(demuxer, + title, + prev_byte, + prev_time, + next_byte, + next_time, + 0); +/* + * printf("timecode: %ld %ld %f %f\n", + * timecode->start_byte, + * timecode->end_byte, + * timecode->start_time, + * timecode->end_time); + */ + + counter_start = (int)next_time; + } + prev_time = next_time; + prev_byte = next_byte; + counter = (int)next_time; + } + +/* Just get the first bytes if not building a toc to get the stream ID's. */ + if(next_byte > 0x100000 && + (!timecode_search || !toc)) done = 1; + } + +/* Get the last timecode */ + if(!toc || !timecode_search) + { + result = mpeg3io_seek(title->fs, title->total_bytes); + if(!result) result = mpeg3_read_prev_packet(demuxer); + } + + if(title->timecode_table && timecode) + { + timecode->end_byte = title->total_bytes; +// timecode->end_byte = mpeg3io_tell(title->fs)/* + demuxer->packet_size */; + timecode->end_time = demuxer->time; + timecode->absolute_end_time = timecode->end_time - timecode->start_time; + } + } + + mpeg3io_seek(title->fs, 0); + demuxer->generating_timecode = 0; + return 0; +} + +int mpeg3demux_print_timecodes(mpeg3_title_t *title, FILE *output) +{ + mpeg3demux_timecode_t *timecode; + int i; + + if(title->timecode_table) + { + for(i = 0; i < title->timecode_table_size; i++) + { + timecode = &title->timecode_table[i]; + + fprintf(output, "REGION: %ld %ld %f %f\n", + timecode->start_byte, + timecode->end_byte, + timecode->start_time, + timecode->end_time); + } + } + return 0; +} + +/* Read the title information from a toc */ +int mpeg3demux_read_titles(mpeg3_demuxer_t *demuxer) +{ + char string1[MPEG3_STRLEN], string2[MPEG3_STRLEN]; + long start_byte, end_byte; + float start_time, end_time; + mpeg3_title_t *title = 0; + mpeg3_t *file = demuxer->file; + +// Eventually use IFO file to generate titles + while(!feof(file->fs->fd)) + { + fscanf(file->fs->fd, "%s %s %ld %f %f %f", + string1, + string2, + &end_byte, + &start_time, + &end_time); + + if(!strncasecmp(string1, "PATH:", 5)) + { + title = demuxer->titles[demuxer->total_titles++] = mpeg3_new_title(file, string2); + + if(demuxer->current_title < 0) + mpeg3demux_open_title(demuxer, 0); + } + else + if(title) + { + start_byte = atol(string2); + if(!strcasecmp(string1, "REGION:")) + { + mpeg3_append_timecode(demuxer, + title, + 0, + 0, + 0, + 0, + 1); + title->timecode_table[title->timecode_table_size - 1].start_byte = start_byte; + title->timecode_table[title->timecode_table_size - 1].end_byte = end_byte; + title->timecode_table[title->timecode_table_size - 1].start_time = start_time; + title->timecode_table[title->timecode_table_size - 1].end_time = end_time; + } + else + if(!strcasecmp(string1, "ASTREAM:")) + demuxer->astream_table[start_byte] = end_byte; + else + if(!strcasecmp(string1, "VSTREAM:")) + demuxer->vstream_table[start_byte] = end_byte; + else + if(!strcasecmp(string1, "SIZE:")) + title->total_bytes = start_byte; + else + if(!strcasecmp(string1, "PACKETSIZE:")) + demuxer->packet_size = start_byte; + } + } + + mpeg3demux_assign_programs(demuxer); + return 0; +} + +int mpeg3demux_copy_titles(mpeg3_demuxer_t *dst, mpeg3_demuxer_t *src) +{ + long i; + mpeg3_t *file = dst->file; + mpeg3_title_t *dst_title, *src_title; + + dst->packet_size = src->packet_size; + dst->total_titles = src->total_titles; + dst->total_programs = src->total_programs; + for(i = 0; i < MPEG3_MAX_STREAMS; i++) + { + dst->astream_table[i] = src->astream_table[i]; + dst->vstream_table[i] = src->vstream_table[i]; + } + for(i = 0; i < src->total_titles; i++) + { + src_title = src->titles[i]; + dst_title = dst->titles[i] = mpeg3_new_title(file, src->titles[i]->fs->path); + mpeg3_copy_title(dst_title, src_title); + } + + mpeg3demux_open_title(dst, src->current_title); + return 0; +} + +int mpeg3demux_print_streams(mpeg3_demuxer_t *demuxer, FILE *toc) +{ + int i; +/* Print the stream information */ + for(i = 0; i < MPEG3_MAX_STREAMS; i++) + { + if(demuxer->astream_table[i]) + fprintf(toc, "ASTREAM: %d %d\n", i, demuxer->astream_table[i]); + + if(demuxer->vstream_table[i]) + fprintf(toc, "VSTREAM: %d %d\n", i, demuxer->vstream_table[i]); + } + return 0; +} + +/* Need a timecode table to do this */ +double mpeg3demux_length(mpeg3_demuxer_t *demuxer) +{ + mpeg3_title_t *title; + int i, j; + double length; + + for(i = demuxer->total_titles - 1; i >= 0; i--) + { + title = demuxer->titles[i]; + for(j = title->timecode_table_size - 1; j >= 0; j--) + { + if(title->timecode_table[j].program == demuxer->current_program) + { + return title->timecode_table[j].end_time - + title->timecode_table[j].start_time + + title->timecode_table[j].absolute_start_time; + } + } + } + + return 1; +} + +int mpeg3demux_eof(mpeg3_demuxer_t *demuxer) +{ + if(demuxer->current_title >= 0) + { + if(mpeg3io_eof(demuxer->titles[demuxer->current_title]->fs) && + demuxer->current_title >= demuxer->total_titles - 1) + return 1; + } + + return 0; +} + +int mpeg3demux_bof(mpeg3_demuxer_t *demuxer) +{ + if(demuxer->current_title >= 0) + { + if(mpeg3io_bof(demuxer->titles[demuxer->current_title]->fs) && + demuxer->current_title <= 0) + return 1; + } + return 0; +} + + +/* For elemental streams seek to a byte */ +int mpeg3demux_seek_byte(mpeg3_demuxer_t *demuxer, long byte) +{ + long current_position; + mpeg3_t *file = demuxer->file; + mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; + + demuxer->data_position = 0; + demuxer->data_size = 0; + + demuxer->error_flag = mpeg3io_seek(title->fs, byte); + + if(!demuxer->error_flag && (file->is_transport_stream || file->is_program_stream)) + { +/* Get on a packet boundary only for system streams. */ + current_position = mpeg3io_tell(title->fs); + if(byte % demuxer->packet_size) + { + demuxer->error_flag |= mpeg3io_seek(title->fs, current_position - (current_position % demuxer->packet_size)); + } + } + return demuxer->error_flag; +} + +/* For programs streams and toc seek to a time */ +int mpeg3demux_seek_time(mpeg3_demuxer_t *demuxer, double new_time) +{ + int i, j, done = 0, result = 0; + double byte_offset, new_byte_offset; + double guess = 0, minimum = 65535; + mpeg3_title_t *title; + mpeg3demux_timecode_t *timecode; + + demuxer->error_flag = 0; + + i = 0; + j = 0; + title = demuxer->titles[i]; + timecode = &title->timecode_table[j]; + +/* Get the title and timecode of the new position */ + while(!demuxer->error_flag && + !(timecode->absolute_start_time <= new_time && + timecode->absolute_end_time > new_time && + timecode->program == demuxer->current_program)) + { +/* Next timecode */ + j++; + if(j >= title->timecode_table_size) + { + i++; + j = 0; + if(i >= demuxer->total_titles) + { + demuxer->error_flag = 1; + return 1; + } + else + { + mpeg3demux_open_title(demuxer, i); + } + } + + title = demuxer->titles[i]; + timecode = &title->timecode_table[j]; + } + +/* Guess the new byte position */ + demuxer->current_timecode = j; + + byte_offset = ((new_time - timecode->absolute_start_time) / + (timecode->absolute_end_time - timecode->absolute_start_time) * + (timecode->end_byte - timecode->start_byte) + + timecode->start_byte); +//printf("mpeg3demux_seek_time %f %f\n", new_time, byte_offset); + + while(!done && !result && byte_offset >= 0) + { + result = mpeg3demux_seek_byte(demuxer, (long)byte_offset); +//printf("seek_time 0 byte %.0f want %f result %d\n", byte_offset, new_time, result); + + if(!result) + { + result = mpeg3_read_next_packet(demuxer); +// printf("seek_time 1 guess %f want %f\n", guess, new_time); + guess = demuxer->time + demuxer->time_offset; + + if(fabs(new_time - guess) >= fabs(minimum)) done = 1; + else + { + minimum = guess - new_time; + new_byte_offset = byte_offset + ((new_time - guess) / + (timecode->end_time - timecode->start_time) * + (timecode->end_byte - timecode->start_byte)); + if(labs((long)new_byte_offset - (long)byte_offset) < demuxer->packet_size) done = 1; + byte_offset = new_byte_offset; + } + } + } + +/* Get one packet before the packet just read */ + if(!result && byte_offset > demuxer->packet_size && minimum > 0) + { + mpeg3_read_prev_packet(demuxer); + mpeg3_read_prev_packet(demuxer); + } +//printf("seek_time %d %d %d\n", demuxer->current_title, demuxer->current_timecode, mpeg3demux_tell(demuxer)); + demuxer->error_flag = result; + return result; +} + +int mpeg3demux_seek_percentage(mpeg3_demuxer_t *demuxer, double percentage) +{ + double total_bytes = 0; + double absolute_position; + long relative_position; + int i, new_title; + mpeg3_title_t *title; + + demuxer->error_flag = 0; + +/* Get the absolute byte position; */ + for(i = 0; i < demuxer->total_titles; i++) + total_bytes += demuxer->titles[i]->total_bytes; + + absolute_position = percentage * total_bytes; + +/* Get the title the byte is inside */ + for(new_title = 0, total_bytes = 0; new_title < demuxer->total_titles; new_title++) + { + total_bytes += demuxer->titles[new_title]->total_bytes; + if(absolute_position < total_bytes) break; + } + + if(new_title >= demuxer->total_titles) + { + new_title = demuxer->total_titles - 1; + } + +/* Got a title */ + title = demuxer->titles[new_title]; + total_bytes -= title->total_bytes; + relative_position = (long)(absolute_position - total_bytes); + +/* Get the timecode the byte is inside */ + for(demuxer->current_timecode = 0; + demuxer->current_timecode < title->timecode_table_size; + demuxer->current_timecode++) + { + if(title->timecode_table[demuxer->current_timecode].start_byte <= relative_position && + title->timecode_table[demuxer->current_timecode].end_byte > relative_position) + { + break; + } + } + + if(demuxer->current_timecode >= title->timecode_table_size) + demuxer->current_timecode = title->timecode_table_size - 1; + +/* Get the nearest timecode in the same program */ + while(demuxer->current_timecode < title->timecode_table_size - 1 && + title->timecode_table[demuxer->current_timecode].program != demuxer->current_program) + { + demuxer->current_timecode++; + } + +/* Open the new title and seek to the correct byte */ + if(new_title != demuxer->current_title) + { + demuxer->error_flag = mpeg3demux_open_title(demuxer, new_title); + } + + if(!demuxer->error_flag) + demuxer->error_flag = mpeg3io_seek(title->fs, relative_position); + + return demuxer->error_flag; +} + +double mpeg3demux_tell_percentage(mpeg3_demuxer_t *demuxer) +{ + double total_bytes = 0; + double position = 0; + int i; + + demuxer->error_flag = 0; + position = mpeg3io_tell(demuxer->titles[demuxer->current_title]->fs); + for(i = 0; i < demuxer->total_titles; i++) + { + if(i == demuxer->current_title) + { + position += total_bytes; + } + total_bytes += demuxer->titles[i]->total_bytes; + } + return position / total_bytes; +} + +double mpeg3demux_get_time(mpeg3_demuxer_t *demuxer) +{ + return demuxer->time; +} + +long mpeg3demux_tell(mpeg3_demuxer_t *demuxer) +{ + return mpeg3io_tell(demuxer->titles[demuxer->current_title]->fs); +} + +long mpeg3demuxer_total_bytes(mpeg3_demuxer_t *demuxer) +{ + mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; + return title->total_bytes; +} + +mpeg3_demuxer_t* mpeg3_get_demuxer(mpeg3_t *file) +{ + if(file->is_program_stream || file->is_transport_stream) + { + if(file->has_audio) return file->atrack[0]->demuxer; + else + if(file->has_video) return file->vtrack[0]->demuxer; + } + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3demux.h b/core/multimedia/opieplayer/libmpeg3/mpeg3demux.h new file mode 100644 index 0000000..9dfd182 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3demux.h @@ -0,0 +1,118 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3DEMUX_H +#define MPEG3DEMUX_H + +#include "mpeg3title.h" +#include + +typedef struct +{ + struct mpeg3_rec* file; +/* Data consisting of the multiplexed packet */ + unsigned char *raw_data; + long raw_offset; + int raw_size; + long packet_size; +/* Only one is on depending on which track owns the demultiplexer. */ + int do_audio; + int do_video; +/* Data consisting of the elementary stream */ + unsigned char *data_buffer; + long data_size; + long data_position; + long data_allocated; +/* Remember when the file descriptor is at the beginning of the packet just read. */ + int reverse; +/* Set to 1 when eof or attempt to read before beginning */ + int error_flag; +/* Temp variables for returning */ + unsigned char next_char; +/* Correction factor for time discontinuity */ + double time_offset; + int generating_timecode; + +/* Titles */ + mpeg3_title_t *titles[MPEG3_MAX_STREAMS]; + int total_titles; + int current_title; + +/* Tables of every stream ID encountered */ + int astream_table[MPEG3_MAX_STREAMS]; /* macro of audio format if audio */ + int vstream_table[MPEG3_MAX_STREAMS]; /* 1 if video */ + +/* Programs */ + int total_programs; + int current_program; + +/* Timecode in the current title */ + int current_timecode; + +/* Byte position in the current title */ + long current_byte; + + int transport_error_indicator; + int payload_unit_start_indicator; + int pid; + int transport_scrambling_control; + int adaptation_field_control; + int continuity_counter; + int is_padding; + int pid_table[MPEG3_PIDMAX]; + int continuity_counters[MPEG3_PIDMAX]; + int total_pids; + int adaptation_fields; + double time; /* Time in seconds */ + int audio_pid; + int video_pid; + int astream; /* Video stream ID being decoded. -1 = select first ID in stream */ + int vstream; /* Audio stream ID being decoded. -1 = select first ID in stream */ + int aformat; /* format of the audio derived from multiplexing codes */ + long program_association_tables; + int table_id; + int section_length; + int transport_stream_id; + long pes_packets; + double pes_audio_time; /* Presentation Time stamps */ + double pes_video_time; /* Presentation Time stamps */ +} mpeg3_demuxer_t; + +/* ========================================================================= */ +/* Entry points */ +/* ========================================================================= */ + +#define mpeg3demux_error(demuxer) (((mpeg3_demuxer_t *)(demuxer))->error_flag) + +#define mpeg3demux_time_offset(demuxer) (((mpeg3_demuxer_t *)(demuxer))->time_offset) + +#define mpeg3demux_current_time(demuxer) (((mpeg3_demuxer_t *)(demuxer))->time + ((mpeg3_demuxer_t *)(demuxer))->time_offset) + +#define mpeg3demux_read_char(demuxer) \ + ((((mpeg3_demuxer_t *)(demuxer))->data_position < ((mpeg3_demuxer_t *)(demuxer))->data_size) ? \ + ((mpeg3_demuxer_t *)(demuxer))->data_buffer[((mpeg3_demuxer_t *)(demuxer))->data_position++] : \ + mpeg3demux_read_char_packet(demuxer)) + +#define mpeg3demux_read_prev_char(demuxer) \ + ((((mpeg3_demuxer_t *)(demuxer))->data_position != 0) ? \ + ((mpeg3_demuxer_t *)(demuxer))->data_buffer[((mpeg3_demuxer_t *)(demuxer))->data_position--] : \ + mpeg3demux_read_prev_char_packet(demuxer)) + + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3io.c b/core/multimedia/opieplayer/libmpeg3/mpeg3io.c new file mode 100644 index 0000000..c5807a7 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3io.c @@ -0,0 +1,127 @@ +#include "mpeg3private.h" +#include "mpeg3protos.h" + +#ifndef _WIN32 +#include +#else + +#endif +#include +#include +#include + +mpeg3_fs_t* mpeg3_new_fs(char *path) +{ + mpeg3_fs_t *fs = (mpeg3_fs_t*)calloc(1, sizeof(mpeg3_fs_t)); + fs->css = mpeg3_new_css(); + strcpy(fs->path, path); + return fs; +} + +int mpeg3_delete_fs(mpeg3_fs_t *fs) +{ + mpeg3_delete_css(fs->css); + free(fs); + return 0; +} + +int mpeg3_copy_fs(mpeg3_fs_t *dst, mpeg3_fs_t *src) +{ + strcpy(dst->path, src->path); + dst->current_byte = 0; + return 0; +} + +long mpeg3io_get_total_bytes(mpeg3_fs_t *fs) +{ +/* + * struct stat st; + * if(stat(fs->path, &st) < 0) return 0; + * return (long)st.st_size; + */ + + fseek(fs->fd, 0, SEEK_END); + fs->total_bytes = ftell(fs->fd); + fseek(fs->fd, 0, SEEK_SET); + return fs->total_bytes; +} + +int mpeg3io_open_file(mpeg3_fs_t *fs) +{ +/* Need to perform authentication before reading a single byte. */ + mpeg3_get_keys(fs->css, fs->path); + + if(!(fs->fd = fopen(fs->path, "rb"))) + { + perror("mpeg3io_open_file"); + return 1; + } + + fs->total_bytes = mpeg3io_get_total_bytes(fs); + + if(!fs->total_bytes) + { + fclose(fs->fd); + return 1; + } + fs->current_byte = 0; + return 0; +} + +int mpeg3io_close_file(mpeg3_fs_t *fs) +{ + if(fs->fd) fclose(fs->fd); + fs->fd = 0; + return 0; +} + +int mpeg3io_read_data(unsigned char *buffer, long bytes, mpeg3_fs_t *fs) +{ + int result = 0; +//printf("read %d bytes\n",bytes); + result = !fread(buffer, 1, bytes, fs->fd); + fs->current_byte += bytes; + return (result && bytes); +} + +int mpeg3io_device(char *path, char *device) +{ + struct stat file_st, device_st; + struct mntent *mnt; + FILE *fp; + + if(stat(path, &file_st) < 0) + { + perror("mpeg3io_device"); + return 1; + } + +#ifndef _WIN32 + fp = setmntent(MOUNTED, "r"); + while(fp && (mnt = getmntent(fp))) + { + if(stat(mnt->mnt_fsname, &device_st) < 0) continue; + if(device_st.st_rdev == file_st.st_dev) + { + strncpy(device, mnt->mnt_fsname, MPEG3_STRLEN); + break; + } + } + endmntent(fp); +#endif + + return 0; +} + +int mpeg3io_seek(mpeg3_fs_t *fs, long byte) +{ + fs->current_byte = byte; + return fseek(fs->fd, byte, SEEK_SET); +} + +int mpeg3io_seek_relative(mpeg3_fs_t *fs, long bytes) +{ + fs->current_byte += bytes; + return fseek(fs->fd, fs->current_byte, SEEK_SET); +} + diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3io.h b/core/multimedia/opieplayer/libmpeg3/mpeg3io.h new file mode 100644 index 0000000..092e411 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3io.h @@ -0,0 +1,74 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3IO_H +#define MPEG3IO_H + + +#include +#include "mpeg3css.h" +#include "mpeg3private.inc" + +/* Filesystem structure */ + +typedef struct +{ + FILE *fd; + mpeg3_css_t *css; /* Encryption object */ + char path[MPEG3_STRLEN]; +/* Hypothetical position of file pointer */ + long current_byte; + long total_bytes; +} mpeg3_fs_t; + +#define mpeg3io_tell(fs) (((mpeg3_fs_t *)(fs))->current_byte) + +// End of file +#define mpeg3io_eof(fs) (((mpeg3_fs_t *)(fs))->current_byte >= ((mpeg3_fs_t *)(fs))->total_bytes) + +// Beginning of file +#define mpeg3io_bof(fs) (((mpeg3_fs_t *)(fs))->current_byte < 0) + + +#define mpeg3io_total_bytes(fs) (((mpeg3_fs_t *)(fs))->total_bytes) + +extern inline unsigned int mpeg3io_read_int32(mpeg3_fs_t *fs) +{ + int a, b, c, d; + unsigned int result; +/* Do not fread. This breaks byte ordering. */ + a = (unsigned char)fgetc(fs->fd); + b = (unsigned char)fgetc(fs->fd); + c = (unsigned char)fgetc(fs->fd); + d = (unsigned char)fgetc(fs->fd); + result = ((int)a << 24) | + ((int)b << 16) | + ((int)c << 8) | + ((int)d); + fs->current_byte += 4; + return result; +} + +extern inline unsigned int mpeg3io_read_char(mpeg3_fs_t *fs) +{ + fs->current_byte++; + return fgetc(fs->fd); +} + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3private.h b/core/multimedia/opieplayer/libmpeg3/mpeg3private.h new file mode 100644 index 0000000..f0e11aa --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3private.h @@ -0,0 +1,62 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3PRIVATE_H +#define MPEG3PRIVATE_H + +#include "mpeg3atrack.h" +#include "mpeg3css.h" +#include "mpeg3io.h" +#include "mpeg3private.inc" +#include "mpeg3title.h" +#include "mpeg3vtrack.h" + +struct mpeg3_rec +{ + mpeg3_fs_t *fs; /* Store entry path here */ + mpeg3_demuxer_t *demuxer; /* Master tables */ + +/* Media specific */ + int has_audio; + int has_video; + int total_astreams; + int total_vstreams; + mpeg3_atrack_t *atrack[MPEG3_MAX_STREAMS]; + mpeg3_vtrack_t *vtrack[MPEG3_MAX_STREAMS]; + +/* Only one of these is set to 1 to specify what kind of stream we have. */ + int is_transport_stream; + int is_program_stream; + int is_audio_stream; /* Elemental stream */ + int is_video_stream; /* Elemental stream */ + long packet_size; +/* Type and stream for getting current percentage */ + int last_type_read; /* 1 - audio 2 - video */ + int last_stream_read; + + int program; /* Number of program to play */ + int cpus; + int have_mmx; +}; + +typedef struct mpeg3_rec mpeg3_t; + + + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3private.inc b/core/multimedia/opieplayer/libmpeg3/mpeg3private.inc new file mode 100644 index 0000000..7e56e7f --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3private.inc @@ -0,0 +1,110 @@ +#ifndef LIBMPEG3_INC +#define LIBMPEG3_INC + +#ifdef _WIN32 + +// Disable some compiler warnings that happen a lot but don't matter +#pragma warning( disable : 4003 ) // not enough parameters for macro +#pragma warning( disable : 4305 ) // truncation frm double to float +#pragma warning( disable : 4715 ) // not all control paths return a value +#pragma warning( disable : 4716 ) // must return a value + +#ifdef LIBMPEG_EXPORTS +#define LIBMPEG_EXPORT __declspec( dllexport ) +#else +#define LIBMPEG_EXPORT __declspec( dllimport ) +#endif + +#ifdef ERROR +#undef ERROR +#include +#undef ERROR +#define ERROR (-1) +#else +#include +#undef ERROR +#endif + +#define inline __inline +#define M_PI 3.14159265358979323846 +#define M_SQRT2 1.41421356237309504880 + +#define pthread_mutexattr_t int +#define pthread_mutexattr_init(a) // Nothing +#define pthread_mutex_t CRITICAL_SECTION +#define pthread_mutex_init(a,b) InitializeCriticalSection(a) +#define pthread_mutex_lock(a) EnterCriticalSection(a) +#define pthread_mutex_unlock(a) LeaveCriticalSection(a) +#define pthread_mutex_destroy(a) //DeleteCriticalSection(a) + +#define pthread_attr_t int +#define pthread_attr_init(a) // Nothing +#define pthread_t unsigned long +#define pthread_create(a,b,c,d) *(a) = _beginthread(c,0,d) +//#define pthread_join(a,b) _endthread(b) +//#define pthread_join(a,b) _cwait(NULL,b,NULL) +#define pthread_join(a,b) + +#define strncasecmp(a,b,c) _strnicmp(a,b,c) +#define strcasecmp(a,b) _stricmp(a,b) +#define bzero(a,b) memset(a,0,b) + +#else + +#define LONGLONG long long +#define ULONGLONG unsigned long long + +#endif + +#ifndef LIBMPEG_EXPORT +#define LIBMPEG_EXPORT +#endif + +#define MPEG3_FLOAT32 mpeg3_real_t +#define MPEG3_INT16 short int +#define MPEG3_INT32 int +#define MPEG3_INT64 long + +#define MPEG3_TOC_PREFIX 0x544f4356 +#define MPEG3_TOC_PREFIXLOWER 0x746f6376 +#define MPEG3_ID3_PREFIX 0x494433 +#define MPEG3_RIFF_CODE 0x52494646 +#define MPEG3_PROC_CPUINFO "/proc/cpuinfo" +#define MPEG3_TS_PACKET_SIZE 188 +#define MPEG3_DVD_PACKET_SIZE 0x800 +#define MPEG3_SYNC_BYTE 0x47 +#define MPEG3_PACK_START_CODE 0x000001ba +#define MPEG3_SEQUENCE_START_CODE 0x000001b3 +#define MPEG3_SEQUENCE_END_CODE 0x000001b7 +#define MPEG3_SYSTEM_START_CODE 0x000001bb +#define MPEG3_STRLEN 1024 +#define MPEG3_PIDMAX 20 /* Maximum number of PIDs in one stream */ +#define MPEG3_PROGRAM_ASSOCIATION_TABLE 0x00 +#define MPEG3_CONDITIONAL_ACCESS_TABLE 0x01 +#define MPEG3_PACKET_START_CODE_PREFIX 0x000001 +#define MPEG3_PRIVATE_STREAM_2 0xbf +#define MPEG3_PADDING_STREAM 0xbe +#define MPEG3_GOP_START_CODE 0x000001b8 +#define MPEG3_PICTURE_START_CODE 0x00000100 +#define MPEG3_EXT_START_CODE 0x000001b5 +#define MPEG3_USER_START_CODE 0x000001b2 +#define MPEG3_SLICE_MIN_START 0x00000101 +#define MPEG3_SLICE_MAX_START 0x000001af +#define MPEG3_AC3_START_CODE 0x0b77 +#define MPEG3_PCM_START_CODE 0x0180 +#define MPEG3_MAX_CPUS 256 +#define MPEG3_MAX_STREAMS 256 +#define MPEG3_MAX_PACKSIZE 262144 +#define MPEG3_CONTIGUOUS_THRESHOLD 10 /* Positive difference before declaring timecodes discontinuous */ +#define MPEG3_PROGRAM_THRESHOLD 5 /* Minimum number of seconds before interleaving programs */ +#define MPEG3_SEEK_THRESHOLD 16 /* Number of frames difference before absolute seeking */ + +/* Values for audio format */ +#define AUDIO_UNKNOWN 0 +#define AUDIO_MPEG 1 +#define AUDIO_AC3 2 +#define AUDIO_PCM 3 +#define AUDIO_AAC 4 +#define AUDIO_JESUS 5 + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3protos.h b/core/multimedia/opieplayer/libmpeg3/mpeg3protos.h new file mode 100644 index 0000000..631336b --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3protos.h @@ -0,0 +1,278 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3PROTOS_H +#define MPEG3PROTOS_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* CSS */ + +mpeg3_css_t* mpeg3_new_css(); + +/* DEMUX */ + +mpeg3_demuxer_t* mpeg3_new_demuxer(mpeg3_t *file, int do_audio, int do_video, int stream_id); +int mpeg3_delete_demuxer(mpeg3_demuxer_t *demuxer); +int mpeg3demux_read_data(mpeg3_demuxer_t *demuxer, unsigned char *output, long size); +unsigned int mpeg3demux_read_int32(mpeg3_demuxer_t *demuxer); +unsigned int mpeg3demux_read_int24(mpeg3_demuxer_t *demuxer); +unsigned int mpeg3demux_read_int16(mpeg3_demuxer_t *demuxer); +double mpeg3demux_length(mpeg3_demuxer_t *demuxer); +mpeg3_demuxer_t* mpeg3_get_demuxer(mpeg3_t *file); +long mpeg3demux_tell(mpeg3_demuxer_t *demuxer); +double mpeg3demux_tell_percentage(mpeg3_demuxer_t *demuxer); +double mpeg3demux_get_time(mpeg3_demuxer_t *demuxer); +int mpeg3demux_eof(mpeg3_demuxer_t *demuxer); +int mpeg3demux_bof(mpeg3_demuxer_t *demuxer); +int mpeg3demux_copy_titles(mpeg3_demuxer_t *dst, mpeg3_demuxer_t *src); +int mpeg3demux_create_title(mpeg3_demuxer_t *demuxer, int timecode_search, FILE *toc); +long mpeg3demuxer_total_bytes(mpeg3_demuxer_t *demuxer); +int mpeg3demux_seek_byte(mpeg3_demuxer_t *demuxer, long byte); +int mpeg3demux_seek_time(mpeg3_demuxer_t *demuxer, double new_time); +int mpeg3demux_seek_percentage(mpeg3_demuxer_t *demuxer, double percentage); +int mpeg3demux_print_streams(mpeg3_demuxer_t *demuxer, FILE *toc); +int mpeg3demux_print_timecodes(mpeg3_title_t *title, FILE *output); +int mpeg3demux_read_titles(mpeg3_demuxer_t *demuxer); +int mpeg3demux_open_title(mpeg3_demuxer_t *demuxer, int title_number); + +/* TITLE */ + +mpeg3_title_t* mpeg3_new_title(mpeg3_t *file, char *path); +int mpeg3_delete_title(mpeg3_title_t *title); +int mpeg3_copy_title(mpeg3_title_t *dst, mpeg3_title_t *src); + + +/* ATRACK */ + +mpeg3_atrack_t* mpeg3_new_atrack(mpeg3_t *file, int stream_id, int is_ac3, mpeg3_demuxer_t *demuxer); +int mpeg3_delete_atrack(mpeg3_t *file, mpeg3_atrack_t *atrack); + +/* VTRACK */ + +mpeg3_vtrack_t* mpeg3_new_vtrack(mpeg3_t *file, int stream_id, mpeg3_demuxer_t *demuxer); +int mpeg3_delete_vtrack(mpeg3_t *file, mpeg3_vtrack_t *vtrack); + +/* AUDIO */ +mpeg3audio_t* mpeg3audio_new(mpeg3_t *file, mpeg3_atrack_t *track, int is_ac3); +int mpeg3audio_delete(mpeg3audio_t *audio); +int mpeg3audio_seek_sample(mpeg3audio_t *audio, long sample); +int mpeg3audio_seek_percentage(mpeg3audio_t *audio, double percentage); +int mpeg3audio_decode_audio(mpeg3audio_t *audio, + mpeg3_real_t *output_f, + short *output_i, int sampleSpacing, + int channel, + long start_position, + long len); +int mpeg3audio_read_raw(mpeg3audio_t *audio, unsigned char *output, long *size, long max_size); +int mpeg3audio_read_ac3_header(mpeg3audio_t *audio); +int mpeg3audio_read_pcm_header(mpeg3audio_t *audio); +int mpeg3audio_synth_mono(mpeg3audio_t *audio, mpeg3_real_t *bandPtr, mpeg3_real_t *samples, int *pnt); +int mpeg3audio_synth_stereo(mpeg3audio_t *audio, mpeg3_real_t *bandPtr, int channel, mpeg3_real_t *out, int *pnt); +int mpeg3audio_replace_buffer(mpeg3audio_t *audio, long new_allocation); +int mpeg3audio_ac3_exponent_unpack(mpeg3audio_t *audio, + mpeg3_ac3bsi_t *bsi, + mpeg3_ac3audblk_t *audblk); +int mpeg3audio_ac3_bit_allocate(mpeg3audio_t *audio, + unsigned int fscod, + mpeg3_ac3bsi_t *bsi, + mpeg3_ac3audblk_t *audblk); +int mpeg3audio_ac3_coeff_unpack(mpeg3audio_t *audio, + mpeg3_ac3bsi_t *bsi, + mpeg3_ac3audblk_t *audblk, + mpeg3ac3_stream_samples_t samples); +int mpeg3audio_ac3_imdct(mpeg3audio_t *audio, + mpeg3_ac3bsi_t *bsi, + mpeg3_ac3audblk_t *audblk, + mpeg3ac3_stream_samples_t samples); +int mpeg3audio_replace_buffer(mpeg3audio_t *audio, long new_allocation); +int mpeg3audio_dct36(mpeg3_real_t *inbuf, mpeg3_real_t *o1, mpeg3_real_t *o2, mpeg3_real_t *wintab, mpeg3_real_t *tsbuf); +int mpeg3audio_dct12(mpeg3_real_t *in,mpeg3_real_t *rawout1,mpeg3_real_t *rawout2,register mpeg3_real_t *wi,register mpeg3_real_t *ts); +int mpeg3audio_read_header(mpeg3audio_t *audio); +int mpeg3audio_do_ac3(mpeg3audio_t *audio); +int mpeg3audio_dolayer2(mpeg3audio_t *audio); +int mpeg3audio_dolayer3(mpeg3audio_t *audio); +int mpeg3audio_do_pcm(mpeg3audio_t *audio); +int mpeg3audio_dct64(mpeg3_real_t *a, mpeg3_real_t *b, mpeg3_real_t *c); +int mpeg3audio_reset_synths(mpeg3audio_t *audio); +int mpeg3audio_prev_header(mpeg3audio_t *audio); +int mpeg3audio_read_layer3_frame(mpeg3audio_t *audio); +int mpeg3audio_new_decode_tables(mpeg3audio_t *audio); +int mpeg3audio_imdct_init(mpeg3audio_t *audio); + + +/* VIDEO */ +mpeg3video_t* mpeg3video_new(mpeg3_t *file, mpeg3_vtrack_t *track); +int mpeg3video_delete(mpeg3video_t *video); +int mpeg3video_read_frame(mpeg3video_t *video, + long frame_number, + unsigned char **output_rows, + int in_x, + int in_y, + int in_w, + int in_h, + int out_w, + int out_h, + int color_model); +int mpeg3video_set_cpus(mpeg3video_t *video, int cpus); +int mpeg3video_set_mmx(mpeg3video_t *video, int use_mmx); +int mpeg3video_seek(mpeg3video_t *video); +int mpeg3video_seek_frame(mpeg3video_t *video, long frame); +int mpeg3video_seek_percentage(mpeg3video_t *video, double percentage); +int mpeg3video_previous_frame(mpeg3video_t *video); +int mpeg3video_drop_frames(mpeg3video_t *video, long frames); +int mpeg3video_read_yuvframe(mpeg3video_t *video, + long frame_number, + char *y_output, + char *u_output, + char *v_output, + int in_x, + int in_y, + int in_w, + int in_h); +int mpeg3video_read_raw(mpeg3video_t *video, unsigned char *output, long *size, long max_size); +int mpeg3video_display_second_field(mpeg3video_t *video); +int mpeg3video_init_output(); +int mpeg3video_get_header(mpeg3video_t *video, int dont_repeat); +int mpeg3video_getpicture(mpeg3video_t *video, int framenum); +int mpeg3video_match_refframes(mpeg3video_t *video); +int mpeg3video_next_code(mpeg3_bits_t* stream, unsigned int code); +int mpeg3video_prev_code(mpeg3_bits_t* stream, unsigned int code); +int mpeg3video_getgophdr(mpeg3video_t *video); +int mpeg3video_present_frame(mpeg3video_t *video); +int mpeg3video_read_frame_backend(mpeg3video_t *video, int skip_bframes); +int mpeg3video_getslicehdr(mpeg3_slice_t *slice, mpeg3video_t *video); +int mpeg3video_get_macroblock_address(mpeg3_slice_t *slice); +int mpeg3video_macroblock_modes(mpeg3_slice_t *slice, + mpeg3video_t *video, + int *pmb_type, + int *pstwtype, + int *pstwclass, + int *pmotion_type, + int *pmv_count, + int *pmv_format, + int *pdmv, + int *pmvscale, + int *pdct_type); +int mpeg3video_motion_vectors(mpeg3_slice_t *slice, + mpeg3video_t *video, + int PMV[2][2][2], + int dmvector[2], + int mv_field_sel[2][2], + int s, + int mv_count, + int mv_format, + int h_r_size, + int v_r_size, + int dmv, + int mvscale); +void mpeg3video_motion_vector(mpeg3_slice_t *slice, + mpeg3video_t *video, + int *PMV, + int *dmvector, + int h_r_size, + int v_r_size, + int dmv, + int mvscale, + int full_pel_vector); +int mpeg3video_get_cbp(mpeg3_slice_t *slice); +int mpeg3video_clearblock(mpeg3_slice_t *slice, int comp, int size); +int mpeg3video_getmpg2intrablock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp, + int dc_dct_pred[]); +int mpeg3video_getintrablock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp, + int dc_dct_pred[]); +int mpeg3video_getmpg2interblock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp); +int mpeg3video_getinterblock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp); +int mpeg3video_reconstruct(mpeg3video_t *video, + int bx, + int by, + int mb_type, + int motion_type, + int PMV[2][2][2], + int mv_field_sel[2][2], + int dmvector[2], + int stwtype); +void mpeg3video_calc_dmv(mpeg3video_t *video, + int DMV[][2], + int *dmvector, + int mvx, + int mvy); + + +/* FILESYSTEM */ + +mpeg3_fs_t* mpeg3_new_fs(char *path); +int mpeg3_delete_fs(mpeg3_fs_t *fs); +int mpeg3io_open_file(mpeg3_fs_t *fs); +int mpeg3io_close_file(mpeg3_fs_t *fs); +int mpeg3io_read_data(unsigned char *buffer, long bytes, mpeg3_fs_t *fs); + +/* BITSTREAM */ +mpeg3_bits_t* mpeg3bits_new_stream(mpeg3_t *file, mpeg3_demuxer_t *demuxer); +unsigned int mpeg3bits_getbits(mpeg3_bits_t* stream, int n); +int mpeg3bits_read_buffer(mpeg3_bits_t* stream, unsigned char *buffer, int bytes); +int mpeg3bits_use_ptr(mpeg3_bits_t* stream, unsigned char *buffer); +int mpeg3bits_use_demuxer(mpeg3_bits_t* stream); +int mpeg3bits_refill(mpeg3_bits_t* stream); +int mpeg3bits_getbitoffset(mpeg3_bits_t *stream); +void mpeg3bits_start_reverse(mpeg3_bits_t* stream); +void mpeg3bits_start_forward(mpeg3_bits_t* stream); +int mpeg3bits_delete_stream(mpeg3_bits_t* stream); +int mpeg3bits_byte_align(mpeg3_bits_t *stream); +int mpeg3bits_seek_start(mpeg3_bits_t* stream); +int mpeg3bits_seek_time(mpeg3_bits_t* stream, double time_position); +int mpeg3bits_seek_byte(mpeg3_bits_t* stream, long position); +int mpeg3bits_seek_percentage(mpeg3_bits_t* stream, double percentage); +unsigned int mpeg3bits_next_startcode(mpeg3_bits_t* stream); +int mpeg3bits_seek_end(mpeg3_bits_t* stream); + +/* MISC */ +int mpeg3_read_toc(mpeg3_t *file); +int mpeg3_generate_toc(FILE *output, char *path, int timecode_search, int print_streams); +int mpeg3_mmx_test(); +int mpeg3io_seek(mpeg3_fs_t *fs, long byte); +int mpeg3io_seek_relative(mpeg3_fs_t *fs, long bytes); +int mpeg3io_device(char *path, char *device); +int mpeg3_decrypt_packet(mpeg3_css_t *css, unsigned char *sector); +int mpeg3_delete_css(mpeg3_css_t *css); +int mpeg3_get_keys(mpeg3_css_t *css, char *path); +int mpeg3_copy_fs(mpeg3_fs_t *dst, mpeg3_fs_t *src); +int mpeg3_min(int x, int y); +int mpeg3_max(int x, int y); +int mpeg3_new_slice_buffer(mpeg3_slice_buffer_t *slice_buffer); +int mpeg3_expand_slice_buffer(mpeg3_slice_buffer_t *slice_buffer); +int mpeg3_delete_slice_decoder(mpeg3_slice_t *slice); +int mpeg3_new_slice_decoder(mpeg3video_t *video, mpeg3_slice_t *slice); +int mpeg3_delete_slice_buffer(mpeg3_slice_buffer_t *slice_buffer); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3title.c b/core/multimedia/opieplayer/libmpeg3/mpeg3title.c new file mode 100644 index 0000000..0c93363 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3title.c @@ -0,0 +1,63 @@ +#include "mpeg3private.h" +#include "mpeg3protos.h" +#include "mpeg3title.h" + + +#include + + +mpeg3_title_t* mpeg3_new_title(mpeg3_t *file, char *path) +{ + mpeg3_title_t *title = (mpeg3_title_t*)calloc(1, sizeof(mpeg3_title_t)); + title->fs = mpeg3_new_fs(path); + title->file = file; + return title; +} + +int mpeg3_delete_title(mpeg3_title_t *title) +{ + mpeg3_delete_fs(title->fs); + if(title->timecode_table_size) + { + free(title->timecode_table); + } + free(title); + return 0; +} + + +int mpeg3_copy_title(mpeg3_title_t *dst, mpeg3_title_t *src) +{ + int i; + + mpeg3_copy_fs(dst->fs, src->fs); + dst->total_bytes = src->total_bytes; + + if(src->timecode_table_size) + { + dst->timecode_table_allocation = src->timecode_table_allocation; + dst->timecode_table_size = src->timecode_table_size; + dst->timecode_table = (mpeg3demux_timecode_t*)calloc(1, sizeof(mpeg3demux_timecode_t) * dst->timecode_table_allocation); + + for(i = 0; i < dst->timecode_table_size; i++) + { + dst->timecode_table[i] = src->timecode_table[i]; + } + } +} + +int mpeg3_dump_title(mpeg3_title_t *title) +{ + int i; + + for(i = 0; i < title->timecode_table_size; i++) + { + printf("%f: %d - %d %f %f %d\n", + title->timecode_table[i].absolute_start_time, + title->timecode_table[i].start_byte, + title->timecode_table[i].end_byte, + title->timecode_table[i].start_time, + title->timecode_table[i].end_time, + title->timecode_table[i].program); + } +} diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3title.h b/core/multimedia/opieplayer/libmpeg3/mpeg3title.h new file mode 100644 index 0000000..a853217 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3title.h @@ -0,0 +1,47 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3TITLE_H +#define MPEG3TITLE_H + +#include "mpeg3io.h" + +typedef struct +{ + long start_byte; + double start_time; + double absolute_start_time; + double absolute_end_time; + long end_byte; + double end_time; + int program; +} mpeg3demux_timecode_t; + +typedef struct +{ + struct mpeg3_rec *file; + mpeg3_fs_t *fs; + long total_bytes; /* Total bytes in file. Critical for seeking and length. */ +/* Timecode table */ + mpeg3demux_timecode_t *timecode_table; + long timecode_table_size; /* Number of entries */ + long timecode_table_allocation; /* Number of available slots */ +} mpeg3_title_t; + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3toc.c b/core/multimedia/opieplayer/libmpeg3/mpeg3toc.c new file mode 100644 index 0000000..84b31cb --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3toc.c @@ -0,0 +1,81 @@ +#include "libmpeg3.h" +#include "mpeg3protos.h" + +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int i; +/* FILE *output; */ + char new_path[1024], *ext; + struct stat st; + long size; + int timecode_search = 0; + + if(argc < 2) + { + fprintf(stderr, "Create a table of contents for a DVD.\n" + " Usage: mpeg3toc [-t] ...\n" + " -t Perform timecode search.\n" + "\n" + " The filenames should be absolute paths unless you plan\n" + " to always run your movie player from the same directory\n" + " as the filename. Alternatively you can edit the toc by\n" + " hand.\n" + " The timecode search allows XMovie to play the Matrix.\n" + "Example: mpeg3toc /cd2/video_ts/vts_01_*.vob > titanic.toc\n"); + exit(1); + } + + for(i = 1; i < argc; i++) + { + if(!strcmp(argv[i], "-t")) + { + timecode_search = 1; + } + else + { +/* Get just name */ + ext = strrchr(argv[i], '/'); + if(ext) + { + ext++; + strcpy(new_path, ext); + } + else + strcpy(new_path, argv[i]); + + +/* Replace suffix */ + ext = strrchr(new_path, '.'); + if(ext) + { + sprintf(ext, ".toc"); + } + else + strcat(new_path, ".toc"); + +/* fprintf(stderr, "Creating %s\n", new_path); */ + + stat(argv[i], &st); + size = (long)st.st_size; + + if(!size) + { + fprintf(stderr, "%s is 0 length. Skipping\n", new_path); + } + else + { +/* Just want the first title's streams */ + if(mpeg3_generate_toc(stdout, argv[i], timecode_search, i == argc - 1)) + { + fprintf(stderr, "Skipping %s\n", argv[i]); + } + } + } + } +} diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3vtrack.c b/core/multimedia/opieplayer/libmpeg3/mpeg3vtrack.c new file mode 100644 index 0000000..dffe9d0 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3vtrack.c @@ -0,0 +1,33 @@ +#include "libmpeg3.h" +#include "mpeg3protos.h" + +#include + +mpeg3_vtrack_t* mpeg3_new_vtrack(mpeg3_t *file, int stream_id, mpeg3_demuxer_t *demuxer) +{ + int result = 0; + mpeg3_vtrack_t *new_vtrack; + new_vtrack = (mpeg3_vtrack_t*)calloc(1, sizeof(mpeg3_vtrack_t)); + new_vtrack->demuxer = mpeg3_new_demuxer(file, 0, 1, stream_id); + if(demuxer) mpeg3demux_copy_titles(new_vtrack->demuxer, demuxer); + new_vtrack->current_position = 0; + +/* Get information about the track here. */ + new_vtrack->video = mpeg3video_new(file, new_vtrack); + if(!new_vtrack->video) + { +/* Failed */ + mpeg3_delete_vtrack(file, new_vtrack); + new_vtrack = 0; + } + return new_vtrack; +} + +int mpeg3_delete_vtrack(mpeg3_t *file, mpeg3_vtrack_t *vtrack) +{ + if(vtrack->video) + mpeg3video_delete(vtrack->video); + if(vtrack->demuxer) + mpeg3_delete_demuxer(vtrack->demuxer); + free(vtrack); +} diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3vtrack.h b/core/multimedia/opieplayer/libmpeg3/mpeg3vtrack.h new file mode 100644 index 0000000..9a3c13d --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3vtrack.h @@ -0,0 +1,39 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3_VTRACK_H +#define MPEG3_VTRACK_H + +#include "mpeg3demux.h" +#include "video/mpeg3video.h" + +struct mpeg3_vtrack_rec +{ + int width; + int height; + float frame_rate; + mpeg3_demuxer_t *demuxer; + mpeg3video_t *video; + long current_position; /* Number of next frame to be played */ + long total_frames; /* Total frames in the file */ +}; + +typedef struct mpeg3_vtrack_rec mpeg3_vtrack_t; + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/ronin_narrow.toc b/core/multimedia/opieplayer/libmpeg3/ronin_narrow.toc new file mode 100644 index 0000000..07cbbf8 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/ronin_narrow.toc @@ -0,0 +1,26 @@ +TOCVERSION 2 +PATH: /cdrom/video_ts/vts_01_1.vob +ASTREAM: 0 2 +VSTREAM: 0 1 +ASTREAM: 1 2 +ASTREAM: 2 2 +SIZE: 1073709056 +PACKETSIZE: 2048 +REGION: 0 35557376 0.000000 51.643256 +REGION: 35559424 307005440 0.000000 440.561122 +REGION: 307007488 556705792 0.000000 423.698289 +REGION: 556707840 792827904 0.000000 423.877622 +REGION: 792829952 967956480 0.000000 292.754122 +REGION: 967958528 1073709056 0.000000 191.720711 +TOCVERSION 2 +PATH: /cdrom/video_ts/vts_01_2.vob +ASTREAM: 0 2 +VSTREAM: 0 1 +ASTREAM: 1 2 +ASTREAM: 2 2 +SIZE: 1073709056 +PACKETSIZE: 2048 +REGION: 0 268423168 191.722344 632.760000 +REGION: 268425216 539189248 0.000000 448.729167 +REGION: 539191296 823230464 0.000000 374.061122 +REGION: 823232512 1073709056 0.000000 421.215667 diff --git a/core/multimedia/opieplayer/libmpeg3/ronin_wide.toc b/core/multimedia/opieplayer/libmpeg3/ronin_wide.toc new file mode 100644 index 0000000..a638304 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/ronin_wide.toc @@ -0,0 +1,47 @@ +TOCVERSION 2 +PATH: /cdrom/video_ts/vts_01_1.vob +SIZE: 1073709056 +PACKETSIZE: 2048 +REGION: 0 33830912 0.000000 51.643256 +REGION: 33832960 321945600 0.000000 440.561122 +REGION: 321947648 566126592 0.000000 423.698289 +REGION: 566128640 804149248 0.000000 423.877622 +REGION: 804151296 979050496 0.000000 292.754122 +REGION: 979052544 1073709056 0.000000 170.331700 +TOCVERSION 2 +PATH: /cdrom/video_ts/vts_01_2.vob +SIZE: 1073709056 +PACKETSIZE: 2048 +REGION: 0 274845696 170.333322 632.760000 +REGION: 274847744 539138048 0.000000 448.729167 +REGION: 539140096 818880512 0.000000 374.061122 +REGION: 818882560 1073709056 0.000000 431.104722 +TOCVERSION 2 +PATH: /cdrom/video_ts/vts_01_3.vob +SIZE: 1073709056 +PACKETSIZE: 2048 +REGION: 0 3602432 431.122100 437.362056 +REGION: 3604480 316528640 0.000000 508.150422 +REGION: 316530688 562409472 0.000000 446.758722 +REGION: 562411520 728014848 0.000000 317.737689 +REGION: 728016896 943480832 0.000000 401.809556 +REGION: 943482880 1073709056 0.000000 177.871922 +TOCVERSION 2 +PATH: /cdrom/video_ts/vts_01_4.vob +SIZE: 1073709056 +PACKETSIZE: 2048 +REGION: 0 224798720 177.873544 496.357422 +REGION: 224800768 469219328 0.000000 431.833522 +REGION: 469221376 718004224 0.000000 426.048756 +REGION: 718006272 978356224 0.000000 411.668422 +REGION: 978358272 1073709056 0.000000 154.534211 +TOCVERSION 2 +PATH: /cdrom/video_ts/vts_01_5.vob +ASTREAM: 0 2 +VSTREAM: 0 1 +ASTREAM: 1 2 +ASTREAM: 2 2 +SIZE: 78041088 +PACKETSIZE: 2048 +REGION: 0 78028800 154.545878 312.853122 +REGION: 78030848 78041088 0.000000 0.006500 diff --git a/core/multimedia/opieplayer/libmpeg3/timecode.h b/core/multimedia/opieplayer/libmpeg3/timecode.h new file mode 100644 index 0000000..21e51e5 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/timecode.h @@ -0,0 +1,31 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef TIMECODE_H +#define TIMECODE_H + +typedef struct +{ + long hour; + long minute; + long second; + long frame; +} mpeg3_timecode_t; + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/Makefile b/core/multimedia/opieplayer/libmpeg3/video/Makefile new file mode 100644 index 0000000..46d8407 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/Makefile @@ -0,0 +1,32 @@ +include ../global_config +export CFLAGS +export CFLAGS_lessopt + +OBJS = \ + getpicture.o \ + headers.o \ + idct.o \ + macroblocks.o \ + mmxtest.o \ + motion.o \ + mpeg3video.o \ + output.o \ + reconstruct.o \ + seek.o \ + slice.o \ + vlc.o + + +all: $(OBJS) $(MMXOBJS2) + +.c.o: + $(CC) -c `./c_flags` -o $@ $< + +.s.o: + $(NASM) -f elf $*.s + +.S.o: + $(CC) -S `./c_flags` $*.S + +clean: + rm -f *.o diff --git a/core/multimedia/opieplayer/libmpeg3/video/c_flags b/core/multimedia/opieplayer/libmpeg3/video/c_flags new file mode 100755 index 0000000..d7943d0 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/c_flags @@ -0,0 +1 @@ +echo $CFLAGS diff --git a/core/multimedia/opieplayer/libmpeg3/video/getpicture.c b/core/multimedia/opieplayer/libmpeg3/video/getpicture.c new file mode 100644 index 0000000..4f67484 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/getpicture.c @@ -0,0 +1,767 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include "vlc.h" + +#include +#include +#include + +int mpeg3video_get_cbp(mpeg3_slice_t *slice) +{ + int code; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + if((code = mpeg3slice_showbits9(slice_buffer)) >= 128) + { + code >>= 4; + mpeg3slice_flushbits(slice_buffer, mpeg3_CBPtab0[code].len); + return mpeg3_CBPtab0[code].val; + } + + if(code >= 8) + { + code >>= 1; + mpeg3slice_flushbits(slice_buffer, mpeg3_CBPtab1[code].len); + return mpeg3_CBPtab1[code].val; + } + + if(code < 1) + { +/* fprintf(stderr,"mpeg3video_get_cbp: invalid coded_block_pattern code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_CBPtab2[code].len); + return mpeg3_CBPtab2[code].val; +} + + +/* set block to zero */ +int mpeg3video_clearblock(mpeg3_slice_t *slice, int comp, int size) +{ + slice->sparse[comp] = 1; + +/* Compiler error */ +/* + * for(i = 0; i < size; i++) + * { + * bzero(slice->block[comp] + sizeof(short) * 64 * i, sizeof(short) * 64); + * } + */ + + if(size == 6) + { + bzero(slice->block[comp], sizeof(short) * 64 * 6); + } + else + { +printf("mpeg3video_clearblock size = %d\n", size); + memset(slice->block[comp], 0, sizeof(short) * 64 * size); + } + return 0; +} + +static inline int mpeg3video_getdclum(mpeg3_slice_buffer_t *slice_buffer) +{ + int code, size, val; +/* decode length */ + code = mpeg3slice_showbits5(slice_buffer); + + if(code < 31) + { + size = mpeg3_DClumtab0[code].val; + mpeg3slice_flushbits(slice_buffer, mpeg3_DClumtab0[code].len); + } + else + { + code = mpeg3slice_showbits9(slice_buffer) - 0x1f0; + size = mpeg3_DClumtab1[code].val; + mpeg3slice_flushbits(slice_buffer, mpeg3_DClumtab1[code].len); + } + + if(size == 0) val = 0; + else + { + val = mpeg3slice_getbits(slice_buffer, size); + if((val & (1 << (size - 1))) == 0) val -= (1 << size) - 1; + } + + return val; +} + + +int mpeg3video_getdcchrom(mpeg3_slice_buffer_t *slice_buffer) +{ + int code, size, val; + +/* decode length */ + code = mpeg3slice_showbits5(slice_buffer); + + if(code < 31) + { + size = mpeg3_DCchromtab0[code].val; + mpeg3slice_flushbits(slice_buffer, mpeg3_DCchromtab0[code].len); + } + else + { + code = mpeg3slice_showbits(slice_buffer, 10) - 0x3e0; + size = mpeg3_DCchromtab1[code].val; + mpeg3slice_flushbits(slice_buffer, mpeg3_DCchromtab1[code].len); + } + + if(size == 0) val = 0; + else + { + val = mpeg3slice_getbits(slice_buffer, size); + if((val & (1 << (size - 1))) == 0) val -= (1 << size) - 1; + } + + return val; +} + + +/* decode one intra coded MPEG-1 block */ + +int mpeg3video_getintrablock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp, + int dc_dct_pred[]) +{ + int val, i, j, sign; + unsigned int code; + mpeg3_DCTtab_t *tab = 0; + short *bp = slice->block[comp]; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + +/* decode DC coefficients */ + if(comp < 4) + bp[0] = (dc_dct_pred[0] += mpeg3video_getdclum(slice_buffer)) << 3; + else + if(comp == 4) + bp[0] = (dc_dct_pred[1] += mpeg3video_getdcchrom(slice_buffer)) << 3; + else + bp[0] = (dc_dct_pred[2] += mpeg3video_getdcchrom(slice_buffer)) << 3; + +#ifdef HAVE_MMX + if(video->have_mmx) + bp[0] <<= 4; +#endif + + if(slice->fault) return 1; + +/* decode AC coefficients */ + for(i = 1; ; i++) + { + code = mpeg3slice_showbits16(slice_buffer); + if(code >= 16384) + tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; + else + if(code >= 1024) tab = &mpeg3_DCTtab0[(code >> 8) - 4]; + else + if(code >= 512) tab = &mpeg3_DCTtab1[(code >> 6) - 8]; + else + if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; + else + if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; + else + if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; + else + if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; + else + if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; + else + { +/* fprintf(stderr, "mpeg3video_getintrablock: invalid Huffman code\n"); */ + slice->fault = 1; + return 1; + } + + mpeg3slice_flushbits(slice_buffer, tab->len); + + if(tab->run == 64) break; /* end_of_block */ + + if(tab->run == 65) + { +/* escape */ + i += mpeg3slice_getbits(slice_buffer, 6); + + if((val = mpeg3slice_getbits(slice_buffer, 8)) == 0) + val = mpeg3slice_getbits(slice_buffer, 8); + else + if(val == 128) + val = mpeg3slice_getbits(slice_buffer, 8) - 256; + else + if(val > 128) + val -= 256; + + if((sign = (val < 0)) != 0) val= -val; + } + else + { + i += tab->run; + val = tab->level; + sign = mpeg3slice_getbit(slice_buffer); + } + + if(i < 64) + j = video->mpeg3_zigzag_scan_table[i]; + else + { + slice->fault = 1; + return 1; + } + + +#ifdef HAVE_MMX + if(video->have_mmx) + { + val = (val * slice->quant_scale * video->intra_quantizer_matrix[j]) << 1; + val = (val - 16) | 16; + } + else +#endif + { + val = (val * slice->quant_scale * video->intra_quantizer_matrix[j]) >> 3; + val = (val - 1) | 1; + } + + bp[j] = sign ? -val : val; + } + + if(j != 0) + { +/* not a sparse matrix ! */ + slice->sparse[comp] = 0; + } + return 0; +} + + +/* decode one non-intra coded MPEG-1 block */ + +int mpeg3video_getinterblock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp) +{ + int val, i, j, sign; + unsigned int code; + mpeg3_DCTtab_t *tab; + short *bp = slice->block[comp]; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + +/* decode AC coefficients */ + for(i = 0; ; i++) + { + code = mpeg3slice_showbits16(slice_buffer); + if(code >= 16384) + { + if(i == 0) + tab = &mpeg3_DCTtabfirst[(code >> 12) - 4]; + else + tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; + } + else + if(code >= 1024) tab = &mpeg3_DCTtab0[(code >> 8) - 4]; + else + if(code >= 512) tab = &mpeg3_DCTtab1[(code >> 6) - 8]; + else + if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; + else + if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; + else + if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; + else + if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; + else + if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; + else + { +// invalid Huffman code + slice->fault = 1; + return 1; + } + + mpeg3slice_flushbits(slice_buffer, tab->len); + +/* end of block */ + if(tab->run == 64) + break; + + if(tab->run == 65) + { +/* escape */ + i += mpeg3slice_getbits(slice_buffer, 6); + if((val = mpeg3slice_getbits(slice_buffer, 8)) == 0) + val = mpeg3slice_getbits(slice_buffer, 8); + else + if(val == 128) + val = mpeg3slice_getbits(slice_buffer, 8) - 256; + else + if(val > 128) + val -= 256; + + if((sign = (val < 0)) != 0) val = -val; + } + else + { + i += tab->run; + val = tab->level; + sign = mpeg3slice_getbit(slice_buffer); + } + + j = video->mpeg3_zigzag_scan_table[i]; + +#ifdef HAVE_MMX + if(video->have_mmx) + { + val = (((val << 1)+1) * slice->quant_scale * video->non_intra_quantizer_matrix[j]); + val = (val - 16) | 16; + } + else +#endif + { + val = (((val << 1)+1) * slice->quant_scale * video->non_intra_quantizer_matrix[j]) >> 4; + val = (val - 1) | 1; + } + + bp[j] = sign ? -val : val; + } + + if(j != 0) + { +/* not a sparse matrix ! */ + slice->sparse[comp] = 0; + } + return 0; +} + + +/* decode one intra coded MPEG-2 block */ +int mpeg3video_getmpg2intrablock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp, + int dc_dct_pred[]) +{ + int val, i, j, sign, nc; + unsigned int code; + mpeg3_DCTtab_t *tab; + short *bp; + int *qmat; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + +/* with data partitioning, data always goes to base layer */ + bp = slice->block[comp]; + + qmat = (comp < 4 || video->chroma_format == CHROMA420) + ? video->intra_quantizer_matrix + : video->chroma_intra_quantizer_matrix; + +/* decode DC coefficients */ + if(comp < 4) + val = (dc_dct_pred[0] += mpeg3video_getdclum(slice_buffer)); + else + if((comp & 1) == 0) + val = (dc_dct_pred[1] += mpeg3video_getdcchrom(slice_buffer)); + else + val = (dc_dct_pred[2] += mpeg3video_getdcchrom(slice_buffer)); + + if(slice->fault) return 1; +#ifdef HAVE_MMX + if(video->have_mmx) + bp[0] = val << (7 - video->dc_prec); + else +#endif + bp[0] = val << (3 - video->dc_prec); + + nc = 0; + +/* decode AC coefficients */ + for(i = 1; ; i++) + { + code = mpeg3slice_showbits16(slice_buffer); + + if(code >= 16384 && !video->intravlc) + tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; + else + if(code >= 1024) + { + if(video->intravlc) + tab = &mpeg3_DCTtab0a[(code >> 8) - 4]; + else + tab = &mpeg3_DCTtab0[(code >> 8) - 4]; + } + else + if(code >= 512) + { + if(video->intravlc) + tab = &mpeg3_DCTtab1a[(code >> 6) - 8]; + else + tab = &mpeg3_DCTtab1[(code >> 6) - 8]; + } + else + if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; + else + if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; + else + if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; + else + if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; + else + if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; + else + { +/* fprintf(stderr,"mpeg3video_getmpg2intrablock: invalid Huffman code\n"); */ + slice->fault = 1; + return 1; + } + + mpeg3slice_flushbits(slice_buffer, tab->len); + +/* end_of_block */ + if(tab->run == 64) + break; + + if(tab->run == 65) + { +/* escape */ + i += mpeg3slice_getbits(slice_buffer, 6); + + val = mpeg3slice_getbits(slice_buffer, 12); + if((val & 2047) == 0) + { +// invalid signed_level (escape) + slice->fault = 1; + return 1; + } + if((sign = (val >= 2048)) != 0) val = 4096 - val; + } + else + { + i += tab->run; + val = tab->level; + sign = mpeg3slice_getbit(slice_buffer); + } + + j = (video->altscan ? video->mpeg3_alternate_scan_table : video->mpeg3_zigzag_scan_table)[i]; + +#ifdef HAVE_MMX + if(video->have_mmx) + val = (val * slice->quant_scale * qmat[j]); + else +#endif + val = (val * slice->quant_scale * qmat[j]) >> 4; + + bp[j] = sign ? -val : val; + nc++; + } + + if(j != 0) + { +/* not a sparse matrix ! */ + slice->sparse[comp] = 0; + } + return 1; +} + + +/* decode one non-intra coded MPEG-2 block */ + +int mpeg3video_getmpg2interblock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp) +{ + int val, i, j, sign, nc; + unsigned int code; + mpeg3_DCTtab_t *tab; + short *bp; + int *qmat; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + +/* with data partitioning, data always goes to base layer */ + bp = slice->block[comp]; + + qmat = (comp < 4 || video->chroma_format == CHROMA420) + ? video->non_intra_quantizer_matrix + : video->chroma_non_intra_quantizer_matrix; + + nc = 0; + +/* decode AC coefficients */ + for(i = 0; ; i++) + { + code = mpeg3slice_showbits16(slice_buffer); + if(code >= 16384) + { + if(i == 0) tab = &mpeg3_DCTtabfirst[(code >> 12) - 4]; + else tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; + } + else + if(code >= 1024) tab = &mpeg3_DCTtab0[(code >> 8) - 4]; + else + if(code >= 512) tab = &mpeg3_DCTtab1[(code >> 6) - 8]; + else + if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; + else + if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; + else + if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; + else + if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; + else + if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; + else + { +// invalid Huffman code + slice->fault = 1; + return 1; + } + + mpeg3slice_flushbits(slice_buffer, tab->len); + +/* end_of_block */ + if(tab->run == 64) + break; + + if(tab->run == 65) + { +/* escape */ + i += mpeg3slice_getbits(slice_buffer, 6); + val = mpeg3slice_getbits(slice_buffer, 12); + if((val & 2047) == 0) + { +/* fprintf(stderr, "mpeg3video_getmpg2interblock: invalid signed_level (escape)\n"); */ + slice->fault = 1; + return 1; + } + if((sign = (val >= 2048)) != 0) val = 4096 - val; + } + else + { + i += tab->run; + val = tab->level; + sign = mpeg3slice_getbit(slice_buffer); + } + + j = (video->altscan ? video->mpeg3_alternate_scan_table : video->mpeg3_zigzag_scan_table)[i]; + +#ifdef HAVE_MMX + if(video->have_mmx) + val = (((val << 1)+1) * slice->quant_scale * qmat[j]) >> 1; + else +#endif + val = (((val << 1)+1) * slice->quant_scale * qmat[j]) >> 5; + + bp[j] = sign ? (-val) : val ; + nc++; + } + + if(j != 0) + { + slice->sparse[comp] = 0; + } + return 0; +} + + +/* decode all macroblocks of the current picture */ +int mpeg3video_get_macroblocks(mpeg3video_t *video, int framenum) +{ + unsigned int code; + mpeg3_slice_buffer_t *slice_buffer; /* Buffer being loaded */ + int i; + int current_buffer; + mpeg3_bits_t *vstream = video->vstream; + +/* Load every slice into a buffer array */ + video->total_slice_buffers = 0; + current_buffer = 0; + while(!mpeg3bits_eof(vstream) && + mpeg3bits_showbits32_noptr(vstream) >= MPEG3_SLICE_MIN_START && + mpeg3bits_showbits32_noptr(vstream) <= MPEG3_SLICE_MAX_START) + { +/* Initialize the buffer */ + if(current_buffer >= video->slice_buffers_initialized) + mpeg3_new_slice_buffer(&(video->slice_buffers[video->slice_buffers_initialized++])); + slice_buffer = &(video->slice_buffers[current_buffer]); + slice_buffer->buffer_size = 0; + slice_buffer->current_position = 0; + slice_buffer->bits_size = 0; + slice_buffer->done = 0; + +/* Read the slice into the buffer including the slice start code */ + do + { +/* Expand buffer */ + if(slice_buffer->buffer_allocation <= slice_buffer->buffer_size) + mpeg3_expand_slice_buffer(slice_buffer); + +/* Load 1 char into buffer */ + slice_buffer->data[slice_buffer->buffer_size++] = mpeg3bits_getbyte_noptr(vstream); + }while(!mpeg3bits_eof(vstream) && + mpeg3bits_showbits24_noptr(vstream) != MPEG3_PACKET_START_CODE_PREFIX); + +/* Pad the buffer to get the last macroblock */ + if(slice_buffer->buffer_allocation <= slice_buffer->buffer_size + 4) + mpeg3_expand_slice_buffer(slice_buffer); + + slice_buffer->data[slice_buffer->buffer_size++] = 0; + slice_buffer->data[slice_buffer->buffer_size++] = 0; + slice_buffer->data[slice_buffer->buffer_size++] = 1; + slice_buffer->data[slice_buffer->buffer_size++] = 0; + slice_buffer->bits_size = 0; + + pthread_mutex_lock(&(slice_buffer->completion_lock)); fflush(stdout); + current_buffer++; + video->total_slice_buffers++; + } + +/* Run the slice decoders */ + if(video->total_slice_buffers > 0) + { + for(i = 0; i < video->total_slice_decoders; i++) + { + if(i == 0 && video->total_slice_decoders > 1) + { + video->slice_decoders[i].current_buffer = 0; + video->slice_decoders[i].buffer_step = 1; + video->slice_decoders[i].last_buffer = (video->total_slice_buffers - 1); + } + else + if(i == 1) + { + video->slice_decoders[i].current_buffer = video->total_slice_buffers - 1; + video->slice_decoders[i].buffer_step = -1; + video->slice_decoders[i].last_buffer = 0; + } + else + { + video->slice_decoders[i].current_buffer = i; + video->slice_decoders[i].buffer_step = 1; + video->slice_decoders[i].last_buffer = video->total_slice_buffers - 1; + } + pthread_mutex_unlock(&(video->slice_decoders[i].input_lock)); + } + } + +/* Wait for the slice decoders to finish */ + if(video->total_slice_buffers > 0) + { + for(i = 0; i < video->total_slice_buffers; i++) + { + pthread_mutex_lock(&(video->slice_buffers[i].completion_lock)); + pthread_mutex_unlock(&(video->slice_buffers[i].completion_lock)); + } + } + return 0; +} + +int mpeg3video_allocate_decoders(mpeg3video_t *video, int decoder_count) +{ + int i; + mpeg3_t *file = video->file; +/* Get the slice decoders */ + if(video->total_slice_decoders != file->cpus) + { + for(i = 0; i < video->total_slice_decoders; i++) + { + mpeg3_delete_slice_decoder(&video->slice_decoders[i]); + } + + for(i = 0; i < file->cpus && i < MPEG3_MAX_CPUS; i++) + { + mpeg3_new_slice_decoder(video, &(video->slice_decoders[i])); + video->slice_decoders[i].thread_number = i; + } + + video->total_slice_decoders = file->cpus; + } + return 0; +} + +/* decode one frame or field picture */ + +int mpeg3video_getpicture(mpeg3video_t *video, int framenum) +{ + int i, result = 0; + mpeg3_t *file = video->file; + + if(video->pict_struct == FRAME_PICTURE && video->secondfield) + { +/* recover from illegal number of field pictures */ + video->secondfield = 0; + } + + if(!video->mpeg2) + { + video->current_repeat = video->repeat_count = 0; + } + + mpeg3video_allocate_decoders(video, file->cpus); + + for(i = 0; i < 3; i++) + { + if(video->pict_type == B_TYPE) + { + video->newframe[i] = video->auxframe[i]; + } + else + { + if(!video->secondfield && !video->current_repeat) + { +/* Swap refframes for I frames */ + unsigned char* tmp = video->oldrefframe[i]; + video->oldrefframe[i] = video->refframe[i]; + video->refframe[i] = tmp; + } + + video->newframe[i] = video->refframe[i]; + } + + if(video->pict_struct == BOTTOM_FIELD) + { +/* Only used if fields are in different pictures */ + video->newframe[i] += (i == 0) ? video->coded_picture_width : video->chrom_width; + } + } + +/* The problem is when a B frame lands on the first repeat and is skipped, */ +/* the second repeat goes for the same bitmap as the skipped repeat, */ +/* so it picks up a frame from 3 frames back. */ +/* The first repeat must consititutively read a B frame if its B frame is going to be */ +/* used in a later repeat. */ + if(!video->current_repeat) + if(!(video->skip_bframes && video->pict_type == B_TYPE) || + (video->repeat_count >= 100 + 100 * video->skip_bframes)) + result = mpeg3video_get_macroblocks(video, framenum); + +/* Set the frame to display */ + video->output_src = 0; + if(framenum > -1 && !result) + { + if(video->pict_struct == FRAME_PICTURE || video->secondfield) + { + if(video->pict_type == B_TYPE) + { + video->output_src = video->auxframe; + } + else + { + video->output_src = video->oldrefframe; + } + } + else + { + mpeg3video_display_second_field(video); + } + } + + if(video->mpeg2) + { + video->current_repeat += 100; + } + + if(video->pict_struct != FRAME_PICTURE) video->secondfield = !video->secondfield; + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/headers.c b/core/multimedia/opieplayer/libmpeg3/video/headers.c new file mode 100644 index 0000000..5274530 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/headers.c @@ -0,0 +1,492 @@ +#include "../mpeg3demux.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" + +#include +#include + +int mpeg3video_getseqhdr(mpeg3video_t *video) +{ + int i; + mpeg3_t *file = video->file; + + int aspect_ratio, picture_rate, vbv_buffer_size; + int constrained_parameters_flag; + int load_intra_quantizer_matrix, load_non_intra_quantizer_matrix; + + video->horizontal_size = mpeg3bits_getbits(video->vstream, 12); + video->vertical_size = mpeg3bits_getbits(video->vstream, 12); + aspect_ratio = mpeg3bits_getbits(video->vstream, 4); + video->framerate_code = mpeg3bits_getbits(video->vstream, 4); + video->bitrate = mpeg3bits_getbits(video->vstream, 18); + mpeg3bits_getbit_noptr(video->vstream); /* marker bit (=1) */ + vbv_buffer_size = mpeg3bits_getbits(video->vstream, 10); + constrained_parameters_flag = mpeg3bits_getbit_noptr(video->vstream); + video->frame_rate = mpeg3_frame_rate_table[video->framerate_code]; + + load_intra_quantizer_matrix = mpeg3bits_getbit_noptr(video->vstream); + if(load_intra_quantizer_matrix) + { + for(i = 0; i < 64; i++) + video->intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); + } + else + { + for(i = 0; i < 64; i++) + video->intra_quantizer_matrix[i] = mpeg3_default_intra_quantizer_matrix[i]; + } + + load_non_intra_quantizer_matrix = mpeg3bits_getbit_noptr(video->vstream); + if(load_non_intra_quantizer_matrix) + { + for(i = 0; i < 64; i++) + video->non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); + } + else + { + for(i = 0; i < 64; i++) + video->non_intra_quantizer_matrix[i] = 16; + } + +/* copy luminance to chrominance matrices */ + for(i = 0; i < 64; i++) + { + video->chroma_intra_quantizer_matrix[i] = video->intra_quantizer_matrix[i]; + video->chroma_non_intra_quantizer_matrix[i] = video->non_intra_quantizer_matrix[i]; + } + + return 0; +} + + +/* decode sequence extension */ + +int mpeg3video_sequence_extension(mpeg3video_t *video) +{ + int prof_lev; + int horizontal_size_extension, vertical_size_extension; + int bit_rate_extension, vbv_buffer_size_extension, low_delay; + int frame_rate_extension_n, frame_rate_extension_d; + int pos = 0; + + video->mpeg2 = 1; + video->scalable_mode = SC_NONE; /* unless overwritten by seq. scal. ext. */ + prof_lev = mpeg3bits_getbyte_noptr(video->vstream); + video->prog_seq = mpeg3bits_getbit_noptr(video->vstream); + video->chroma_format = mpeg3bits_getbits(video->vstream, 2); + horizontal_size_extension = mpeg3bits_getbits(video->vstream, 2); + vertical_size_extension = mpeg3bits_getbits(video->vstream, 2); + bit_rate_extension = mpeg3bits_getbits(video->vstream, 12); + mpeg3bits_getbit_noptr(video->vstream); + vbv_buffer_size_extension = mpeg3bits_getbyte_noptr(video->vstream); + low_delay = mpeg3bits_getbit_noptr(video->vstream); + frame_rate_extension_n = mpeg3bits_getbits(video->vstream, 2); + frame_rate_extension_d = mpeg3bits_getbits(video->vstream, 5); + video->horizontal_size = (horizontal_size_extension << 12) | (video->horizontal_size & 0x0fff); + video->vertical_size = (vertical_size_extension << 12) | (video->vertical_size & 0x0fff); +} + + +/* decode sequence display extension */ + +int mpeg3video_sequence_display_extension(mpeg3video_t *video) +{ + int colour_primaries = 0, transfer_characteristics = 0; + int display_horizontal_size, display_vertical_size; + int pos = 0; + int video_format = mpeg3bits_getbits(video->vstream, 3); + int colour_description = mpeg3bits_getbit_noptr(video->vstream); + + if(colour_description) + { + colour_primaries = mpeg3bits_getbyte_noptr(video->vstream); + transfer_characteristics = mpeg3bits_getbyte_noptr(video->vstream); + video->matrix_coefficients = mpeg3bits_getbyte_noptr(video->vstream); + } + + display_horizontal_size = mpeg3bits_getbits(video->vstream, 14); + mpeg3bits_getbit_noptr(video->vstream); + display_vertical_size = mpeg3bits_getbits(video->vstream, 14); +} + + +/* decode quant matrix entension */ + +int mpeg3video_quant_matrix_extension(mpeg3video_t *video) +{ + int i; + int load_intra_quantiser_matrix, load_non_intra_quantiser_matrix; + int load_chroma_intra_quantiser_matrix; + int load_chroma_non_intra_quantiser_matrix; + int pos = 0; + + if((load_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) + { + for(i = 0; i < 64; i++) + { + video->chroma_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] + = video->intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] + = mpeg3bits_getbyte_noptr(video->vstream); + } + } + + if((load_non_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) + { + for (i = 0; i < 64; i++) + { + video->chroma_non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] + = video->non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] + = mpeg3bits_getbyte_noptr(video->vstream); + } + } + + if((load_chroma_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) + { + for(i = 0; i < 64; i++) + video->chroma_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); + } + + if((load_chroma_non_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) + { + for(i = 0; i < 64; i++) + video->chroma_non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); + } +} + + +/* decode sequence scalable extension */ + +int mpeg3video_sequence_scalable_extension(mpeg3video_t *video) +{ + int layer_id; + + video->scalable_mode = mpeg3bits_getbits(video->vstream, 2) + 1; /* add 1 to make SC_DP != SC_NONE */ + layer_id = mpeg3bits_getbits(video->vstream, 4); + + if(video->scalable_mode == SC_SPAT) + { + video->llw = mpeg3bits_getbits(video->vstream, 14); /* lower_layer_prediction_horizontal_size */ + mpeg3bits_getbit_noptr(video->vstream); + video->llh = mpeg3bits_getbits(video->vstream, 14); /* lower_layer_prediction_vertical_size */ + video->hm = mpeg3bits_getbits(video->vstream, 5); + video->hn = mpeg3bits_getbits(video->vstream, 5); + video->vm = mpeg3bits_getbits(video->vstream, 5); + video->vn = mpeg3bits_getbits(video->vstream, 5); + } + + if(video->scalable_mode == SC_TEMP) + fprintf(stderr, "mpeg3video_sequence_scalable_extension: temporal scalability not implemented\n"); +} + + +/* decode picture display extension */ + +int mpeg3video_picture_display_extension(mpeg3video_t *video) +{ + int n, i; + short frame_centre_horizontal_offset[3]; + short frame_centre_vertical_offset[3]; + + if(video->prog_seq || video->pict_struct != FRAME_PICTURE) + n = 1; + else + n = video->repeatfirst ? 3 : 2; + + for(i = 0; i < n; i++) + { + frame_centre_horizontal_offset[i] = (short)mpeg3bits_getbits(video->vstream, 16); + mpeg3bits_getbit_noptr(video->vstream); + frame_centre_vertical_offset[i] = (short)mpeg3bits_getbits(video->vstream, 16); + mpeg3bits_getbit_noptr(video->vstream); + } +} + + +/* decode picture coding extension */ + +int mpeg3video_picture_coding_extension(mpeg3video_t *video) +{ + int chroma_420_type, composite_display_flag; + int v_axis = 0, field_sequence = 0, sub_carrier = 0, burst_amplitude = 0, sub_carrier_phase = 0; + + video->h_forw_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; + video->v_forw_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; + video->h_back_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; + video->v_back_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; + video->dc_prec = mpeg3bits_getbits(video->vstream, 2); + video->pict_struct = mpeg3bits_getbits(video->vstream, 2); + video->topfirst = mpeg3bits_getbit_noptr(video->vstream); + video->frame_pred_dct = mpeg3bits_getbit_noptr(video->vstream); + video->conceal_mv = mpeg3bits_getbit_noptr(video->vstream); + video->qscale_type = mpeg3bits_getbit_noptr(video->vstream); + video->intravlc = mpeg3bits_getbit_noptr(video->vstream); + video->altscan = mpeg3bits_getbit_noptr(video->vstream); + video->repeatfirst = mpeg3bits_getbit_noptr(video->vstream); + chroma_420_type = mpeg3bits_getbit_noptr(video->vstream); + video->prog_frame = mpeg3bits_getbit_noptr(video->vstream); + + if(video->repeat_count > 100) + video->repeat_count = 0; + video->repeat_count += 100; + + video->current_repeat = 0; + + if(video->prog_seq) + { + if(video->repeatfirst) + { + if(video->topfirst) + video->repeat_count += 200; + else + video->repeat_count += 100; + } + } + else + if(video->prog_frame) + { + if(video->repeatfirst) + { + video->repeat_count += 50; + } + } + +/*printf("mpeg3video_picture_coding_extension %d\n", video->repeat_count); */ + composite_display_flag = mpeg3bits_getbit_noptr(video->vstream); + + if(composite_display_flag) + { + v_axis = mpeg3bits_getbit_noptr(video->vstream); + field_sequence = mpeg3bits_getbits(video->vstream, 3); + sub_carrier = mpeg3bits_getbit_noptr(video->vstream); + burst_amplitude = mpeg3bits_getbits(video->vstream, 7); + sub_carrier_phase = mpeg3bits_getbyte_noptr(video->vstream); + } +} + + +/* decode picture spatial scalable extension */ + +int mpeg3video_picture_spatial_scalable_extension(mpeg3video_t *video) +{ + video->pict_scal = 1; /* use spatial scalability in this picture */ + + video->lltempref = mpeg3bits_getbits(video->vstream, 10); + mpeg3bits_getbit_noptr(video->vstream); + video->llx0 = mpeg3bits_getbits(video->vstream, 15); + if(video->llx0 >= 16384) video->llx0 -= 32768; + mpeg3bits_getbit_noptr(video->vstream); + video->lly0 = mpeg3bits_getbits(video->vstream, 15); + if(video->lly0 >= 16384) video->lly0 -= 32768; + video->stwc_table_index = mpeg3bits_getbits(video->vstream, 2); + video->llprog_frame = mpeg3bits_getbit_noptr(video->vstream); + video->llfieldsel = mpeg3bits_getbit_noptr(video->vstream); +} + + +/* decode picture temporal scalable extension + * + * not implemented + * + */ + +int mpeg3video_picture_temporal_scalable_extension(mpeg3video_t *video) +{ + fprintf(stderr, "mpeg3video_picture_temporal_scalable_extension: temporal scalability not supported\n"); +} + + +/* decode extension and user data */ + +int mpeg3video_ext_user_data(mpeg3video_t *video) +{ + int code = mpeg3bits_next_startcode(video->vstream); + + + while(code == MPEG3_EXT_START_CODE || code == MPEG3_USER_START_CODE && + !mpeg3bits_eof(video->vstream)) + { + mpeg3bits_refill(video->vstream); + + if(code == MPEG3_EXT_START_CODE) + { + int ext_id = mpeg3bits_getbits(video->vstream, 4); + switch(ext_id) + { + case SEQ_ID: + mpeg3video_sequence_extension(video); + break; + case DISP_ID: + mpeg3video_sequence_display_extension(video); + break; + case QUANT_ID: + mpeg3video_quant_matrix_extension(video); + break; + case SEQSCAL_ID: + mpeg3video_sequence_scalable_extension(video); + break; + case PANSCAN_ID: + mpeg3video_picture_display_extension(video); + break; + case CODING_ID: + mpeg3video_picture_coding_extension(video); + break; + case SPATSCAL_ID: + mpeg3video_picture_spatial_scalable_extension(video); + break; + case TEMPSCAL_ID: + mpeg3video_picture_temporal_scalable_extension(video); + break; + default: + fprintf(stderr,"mpeg3video_ext_user_data: reserved extension start code ID %d\n", ext_id); + break; + } + } + code = mpeg3bits_next_startcode(video->vstream); + } +} + + +/* decode group of pictures header */ + +int mpeg3video_getgophdr(mpeg3video_t *video) +{ + int drop_flag, closed_gop, broken_link; + + drop_flag = mpeg3bits_getbit_noptr(video->vstream); + video->gop_timecode.hour = mpeg3bits_getbits(video->vstream, 5); + video->gop_timecode.minute = mpeg3bits_getbits(video->vstream, 6); + mpeg3bits_getbit_noptr(video->vstream); + video->gop_timecode.second = mpeg3bits_getbits(video->vstream, 6); + video->gop_timecode.frame = mpeg3bits_getbits(video->vstream, 6); + closed_gop = mpeg3bits_getbit_noptr(video->vstream); + broken_link = mpeg3bits_getbit_noptr(video->vstream); + +/* + * printf("%d:%d:%d:%d %d %d %d\n", video->gop_timecode.hour, video->gop_timecode.minute, video->gop_timecode.second, video->gop_timecode.frame, + * drop_flag, closed_gop, broken_link); + */ + return mpeg3bits_error(video->vstream); +} + +/* decode picture header */ + +int mpeg3video_getpicturehdr(mpeg3video_t *video) +{ + int temp_ref, vbv_delay; + + video->pict_scal = 0; /* unless overwritten by pict. spat. scal. ext. */ + + temp_ref = mpeg3bits_getbits(video->vstream, 10); + video->pict_type = mpeg3bits_getbits(video->vstream, 3); + vbv_delay = mpeg3bits_getbits(video->vstream, 16); + + if(video->pict_type == P_TYPE || video->pict_type == B_TYPE) + { + video->full_forw = mpeg3bits_getbit_noptr(video->vstream); + video->forw_r_size = mpeg3bits_getbits(video->vstream, 3) - 1; + } + + if(video->pict_type == B_TYPE) + { + video->full_back = mpeg3bits_getbit_noptr(video->vstream); + video->back_r_size = mpeg3bits_getbits(video->vstream, 3) - 1; + } + +/* get extra bit picture */ + while(mpeg3bits_getbit_noptr(video->vstream) && + !mpeg3bits_eof(video->vstream)) mpeg3bits_getbyte_noptr(video->vstream); + return 0; +} + + +int mpeg3video_get_header(mpeg3video_t *video, int dont_repeat) +{ + unsigned int code; + +/* a sequence header should be found before returning from `getheader' the */ +/* first time (this is to set horizontal/vertical size properly) */ + +/* Repeat the frame until it's less than 1 count from repeat_count */ + if(video->repeat_count - video->current_repeat >= 100 && !dont_repeat) + { + return 0; + } + + if(dont_repeat) + { + video->repeat_count = 0; + video->current_repeat = 0; + } + else + video->repeat_count -= video->current_repeat; + + while(1) + { +/* look for startcode */ + code = mpeg3bits_next_startcode(video->vstream); + if(mpeg3bits_eof(video->vstream)) return 1; + if(code != MPEG3_SEQUENCE_END_CODE) mpeg3bits_refill(video->vstream); + + switch(code) + { + case MPEG3_SEQUENCE_START_CODE: + video->found_seqhdr = 1; + mpeg3video_getseqhdr(video); + mpeg3video_ext_user_data(video); + break; + + case MPEG3_GOP_START_CODE: + mpeg3video_getgophdr(video); + mpeg3video_ext_user_data(video); + break; + + case MPEG3_PICTURE_START_CODE: + mpeg3video_getpicturehdr(video); + mpeg3video_ext_user_data(video); + if(video->found_seqhdr) return 0; /* Exit here */ + break; + + case MPEG3_SEQUENCE_END_CODE: +// Continue until the end + mpeg3bits_refill(video->vstream); + break; + + default: + break; + } + } + return 1; /* Shouldn't be reached. */ +} + +int mpeg3video_ext_bit_info(mpeg3_slice_buffer_t *slice_buffer) +{ + while(mpeg3slice_getbit(slice_buffer)) mpeg3slice_getbyte(slice_buffer); + return 0; +} + +/* decode slice header */ +int mpeg3video_getslicehdr(mpeg3_slice_t *slice, mpeg3video_t *video) +{ + int slice_vertical_position_extension, intra_slice; + int qs; + + slice_vertical_position_extension = (video->mpeg2 && video->vertical_size > 2800) ? + mpeg3slice_getbits(slice->slice_buffer, 3) : 0; + + if(video->scalable_mode == SC_DP) slice->pri_brk = mpeg3slice_getbits(slice->slice_buffer, 7); + + qs = mpeg3slice_getbits(slice->slice_buffer, 5); + slice->quant_scale = video->mpeg2 ? (video->qscale_type ? mpeg3_non_linear_mquant_table[qs] : (qs << 1)) : qs; + + if(mpeg3slice_getbit(slice->slice_buffer)) + { + intra_slice = mpeg3slice_getbit(slice->slice_buffer); + mpeg3slice_getbits(slice->slice_buffer, 7); + mpeg3video_ext_bit_info(slice->slice_buffer); + } + else + intra_slice = 0; + + return slice_vertical_position_extension; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/idct.c b/core/multimedia/opieplayer/libmpeg3/video/idct.c new file mode 100644 index 0000000..c79f90a --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/idct.c @@ -0,0 +1,160 @@ +#include "idct.h" +#include + +/**********************************************************/ +/* inverse two dimensional DCT, Chen-Wang algorithm */ +/* (cf. IEEE ASSP-32, pp. 803-816, Aug. 1984) */ +/* 32-bit integer arithmetic (8 bit coefficients) */ +/* 11 mults, 29 adds per DCT */ +/* sE, 18.8.91 */ +/**********************************************************/ +/* coefficients extended to 12 bit for IEEE1180-1990 */ +/* compliance sE, 2.1.94 */ +/**********************************************************/ + +/* this code assumes >> to be a two's-complement arithmetic */ +/* right shift: (-2)>>1 == -1 , (-3)>>1 == -2 */ + +#define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */ +#define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */ +#define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */ +#define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */ +#define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */ +#define W7 565 /* 2048*sqrt(2)*cos(7*pi/16) */ + +/* row (horizontal) IDCT + * + * 7 pi 1 + * dst[k] = sum c[l] * src[l] * cos( -- * ( k + - ) * l ) + * l=0 8 2 + * + * where: c[0] = 128 + * c[1..7] = 128*sqrt(2) + */ + +int mpeg3video_idctrow(short *blk) +{ + int x0, x1, x2, x3, x4, x5, x6, x7, x8; + + /* shortcut */ + if (!((x1 = blk[4]<<11) | (x2 = blk[6]) | (x3 = blk[2]) | + (x4 = blk[1]) | (x5 = blk[7]) | (x6 = blk[5]) | (x7 = blk[3]))) + { + blk[0]=blk[1]=blk[2]=blk[3]=blk[4]=blk[5]=blk[6]=blk[7]=blk[0]<<3; + return 0; + } + + x0 = (blk[0]<<11) + 128; /* for proper rounding in the fourth stage */ + + /* first stage */ + x8 = W7*(x4+x5); + x4 = x8 + (W1-W7)*x4; + x5 = x8 - (W1+W7)*x5; + x8 = W3*(x6+x7); + x6 = x8 - (W3-W5)*x6; + x7 = x8 - (W3+W5)*x7; + + /* second stage */ + x8 = x0 + x1; + x0 -= x1; + x1 = W6*(x3+x2); + x2 = x1 - (W2+W6)*x2; + x3 = x1 + (W2-W6)*x3; + x1 = x4 + x6; + x4 -= x6; + x6 = x5 + x7; + x5 -= x7; + + /* third stage */ + x7 = x8 + x3; + x8 -= x3; + x3 = x0 + x2; + x0 -= x2; + x2 = (181*(x4+x5)+128)>>8; + x4 = (181*(x4-x5)+128)>>8; + + /* fourth stage */ + blk[0] = (x7+x1)>>8; + blk[1] = (x3+x2)>>8; + blk[2] = (x0+x4)>>8; + blk[3] = (x8+x6)>>8; + blk[4] = (x8-x6)>>8; + blk[5] = (x0-x4)>>8; + blk[6] = (x3-x2)>>8; + blk[7] = (x7-x1)>>8; + + return 1; +} + +/* column (vertical) IDCT + * + * 7 pi 1 + * dst[8*k] = sum c[l] * src[8*l] * cos( -- * ( k + - ) * l ) + * l=0 8 2 + * + * where: c[0] = 1/1024 + * c[1..7] = (1/1024)*sqrt(2) + */ + +int mpeg3video_idctcol(short *blk) +{ + int x0, x1, x2, x3, x4, x5, x6, x7, x8; + + /* shortcut */ + if (!((x1 = (blk[8 * 4]<<8)) | (x2 = blk[8 * 6]) | (x3 = blk[8 * 2]) | + (x4 = blk[8*1]) | (x5 = blk[8 * 7]) | (x6 = blk[8 * 5]) | (x7 = blk[8 * 3]))){ + blk[8*0]=blk[8*1]=blk[8 * 2]=blk[8 * 3]=blk[8 * 4]=blk[8 * 5]=blk[8 * 6]=blk[8 * 7]= + (blk[8*0]+32)>>6; + return 0; + } + + x0 = (blk[8*0]<<8) + 8192; + + /* first stage */ + x8 = W7*(x4+x5) + 4; + x4 = (x8+(W1-W7)*x4)>>3; + x5 = (x8-(W1+W7)*x5)>>3; + x8 = W3*(x6+x7) + 4; + x6 = (x8-(W3-W5)*x6)>>3; + x7 = (x8-(W3+W5)*x7)>>3; + + /* second stage */ + x8 = x0 + x1; + x0 -= x1; + x1 = W6*(x3+x2) + 4; + x2 = (x1-(W2+W6)*x2)>>3; + x3 = (x1+(W2-W6)*x3)>>3; + x1 = x4 + x6; + x4 -= x6; + x6 = x5 + x7; + x5 -= x7; + + /* third stage */ + x7 = x8 + x3; + x8 -= x3; + x3 = x0 + x2; + x0 -= x2; + x2 = (181 * (x4 + x5) + 128) >> 8; + x4 = (181 * (x4 - x5) + 128) >> 8; + + /* fourth stage */ + blk[8 * 0] = (x7 + x1) >> 14; + blk[8 * 1] = (x3 + x2) >> 14; + blk[8 * 2] = (x0 + x4) >> 14; + blk[8 * 3] = (x8 + x6) >> 14; + blk[8 * 4] = (x8 - x6) >> 14; + blk[8 * 5] = (x0 - x4) >> 14; + blk[8 * 6] = (x3 - x2) >> 14; + blk[8 * 7] = (x7 - x1) >> 14; + + return 1; +} + + +/* two dimensional inverse discrete cosine transform */ +void mpeg3video_idct_conversion(short* block) +{ + int i; + for(i = 0; i < 8; i++) mpeg3video_idctrow(block + 8 * i); + for(i = 0; i < 8; i++) mpeg3video_idctcol(block + i); +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/idct.h b/core/multimedia/opieplayer/libmpeg3/video/idct.h new file mode 100644 index 0000000..f0aa1d8 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/idct.h @@ -0,0 +1,24 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef IDCT_H +#define IDCT_H + + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/layerdata.h b/core/multimedia/opieplayer/libmpeg3/video/layerdata.h new file mode 100644 index 0000000..3ef0f90 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/layerdata.h @@ -0,0 +1,35 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef LAYERDATA_H +#define LAYERDATA_H + +typedef struct +{ +/* sequence header */ + int intra_quantizer_matrix[64], non_intra_quantizer_matrix[64]; + int chroma_intra_quantizer_matrix[64], chroma_non_intra_quantizer_matrix[64]; + int mpeg2; + int qscale_type, altscan; /* picture coding extension */ + int pict_scal; /* picture spatial scalable extension */ + int scalable_mode; /* sequence scalable extension */ +} mpeg3_layerdata_t; + + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/macroblocks.c b/core/multimedia/opieplayer/libmpeg3/video/macroblocks.c new file mode 100644 index 0000000..11e17c1 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/macroblocks.c @@ -0,0 +1,338 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include "slice.h" +#include "vlc.h" + +#include + +int mpeg3video_get_macroblock_address(mpeg3_slice_t *slice) +{ + int code, val = 0; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + while((code = mpeg3slice_showbits(slice_buffer, 11)) < 24) + { +/* Is not macroblock_stuffing */ + if(code != 15) + { +/* Is macroblock_escape */ + if(code == 8) + { + val += 33; + } + else + { +/* fprintf(stderr, "mpeg3video_get_macroblock_address: invalid macroblock_address_increment code\n"); */ + slice->fault = 1; + return 1; + } + } + + mpeg3slice_flushbits(slice_buffer, 11); + } + + if(code >= 1024) + { + mpeg3slice_flushbit(slice_buffer); + return val + 1; + } + + if(code >= 128) + { + code >>= 6; + mpeg3slice_flushbits(slice_buffer, mpeg3_MBAtab1[code].len); + return val + mpeg3_MBAtab1[code].val; + } + + code -= 24; + mpeg3slice_flushbits(slice_buffer, mpeg3_MBAtab2[code].len); + + return val + mpeg3_MBAtab2[code].val; +} + +/* macroblock_type for pictures with spatial scalability */ + +static inline int mpeg3video_getsp_imb_type(mpeg3_slice_t *slice) +{ +// ### This looks wrong. +// slice_buffer is used without being initialised and slice is not used +// mpeg3_slice_buffer_t *slice_buffer = slice_buffer; +// I think this would make more sense and might be what is intended + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + unsigned int code = mpeg3slice_showbits(slice_buffer, 4); + if(!code) + { +/* fprintf(stderr,"mpeg3video_getsp_imb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_spIMBtab[code].len); + return mpeg3_spIMBtab[code].val; +} + +static inline int mpeg3video_getsp_pmb_type(mpeg3_slice_t *slice) +{ + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + int code = mpeg3slice_showbits(slice_buffer, 7); + if(code < 2) + { +/* fprintf(stderr,"mpeg3video_getsp_pmb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + if(code >= 16) + { + code >>= 3; + mpeg3slice_flushbits(slice_buffer, mpeg3_spPMBtab0[code].len); + + return mpeg3_spPMBtab0[code].val; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_spPMBtab1[code].len); + return mpeg3_spPMBtab1[code].val; +} + +static inline int mpeg3video_getsp_bmb_type(mpeg3_slice_t *slice) +{ + mpeg3_VLCtab_t *p; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + int code = mpeg3slice_showbits9(slice_buffer); + + if(code >= 64) + p = &mpeg3_spBMBtab0[(code >> 5) - 2]; + else + if(code >= 16) + p = &mpeg3_spBMBtab1[(code >> 2) - 4]; + else + if(code >= 8) + p = &mpeg3_spBMBtab2[code - 8]; + else + { +/* fprintf(stderr,"mpeg3video_getsp_bmb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, p->len); + return p->val; +} + +static inline int mpeg3video_get_imb_type(mpeg3_slice_t *slice) +{ + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + if(mpeg3slice_getbit(slice_buffer)) + { + return 1; + } + + if(!mpeg3slice_getbit(slice_buffer)) + { +/* fprintf(stderr,"mpeg3video_get_imb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + } + + return 17; +} + +static inline int mpeg3video_get_pmb_type(mpeg3_slice_t *slice) +{ + int code; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + if((code = mpeg3slice_showbits(slice_buffer, 6)) >= 8) + { + code >>= 3; + mpeg3slice_flushbits(slice_buffer, mpeg3_PMBtab0[code].len); + return mpeg3_PMBtab0[code].val; + } + + if(code == 0) + { +/* fprintf(stderr,"mpeg3video_get_pmb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_PMBtab1[code].len); + return mpeg3_PMBtab1[code].val; +} + +static inline int mpeg3video_get_bmb_type(mpeg3_slice_t *slice) +{ + int code; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + if((code = mpeg3slice_showbits(slice_buffer, 6)) >= 8) + { + code >>= 2; + mpeg3slice_flushbits(slice_buffer, mpeg3_BMBtab0[code].len); + return mpeg3_BMBtab0[code].val; + } + + if(code == 0) + { +/* fprintf(stderr,"mpeg3video_get_bmb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_BMBtab1[code].len); + + return mpeg3_BMBtab1[code].val; +} + +static inline int mpeg3video_get_dmb_type(mpeg3_slice_t *slice) +{ + if(!mpeg3slice_getbit(slice->slice_buffer)) + { +/* fprintf(stderr,"mpeg3video_get_dmb_type: invalid macroblock_type code\n"); */ + slice->fault=1; + } + + return 1; +} + + +static inline int mpeg3video_get_snrmb_type(mpeg3_slice_t *slice) +{ + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + int code = mpeg3slice_showbits(slice_buffer, 3); + + if(code == 0) + { +/* fprintf(stderr,"mpeg3video_get_snrmb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_SNRMBtab[code].len); + return mpeg3_SNRMBtab[code].val; +} + +int mpeg3video_get_mb_type(mpeg3_slice_t *slice, mpeg3video_t *video) +{ + if(video->scalable_mode == SC_SNR) + { + return mpeg3video_get_snrmb_type(slice); + } + else + { + switch(video->pict_type) + { + case I_TYPE: return video->pict_scal ? mpeg3video_getsp_imb_type(slice) : mpeg3video_get_imb_type(slice); + case P_TYPE: return video->pict_scal ? mpeg3video_getsp_pmb_type(slice) : mpeg3video_get_pmb_type(slice); + case B_TYPE: return video->pict_scal ? mpeg3video_getsp_bmb_type(slice) : mpeg3video_get_bmb_type(slice); + case D_TYPE: return mpeg3video_get_dmb_type(slice); + default: + /*fprintf(stderr, "mpeg3video_getmbtype: unknown coding type\n"); */ + break; +/* MPEG-1 only, not implemented */ + } + } + + return 0; +} + +int mpeg3video_macroblock_modes(mpeg3_slice_t *slice, + mpeg3video_t *video, + int *pmb_type, + int *pstwtype, + int *pstwclass, + int *pmotion_type, + int *pmv_count, + int *pmv_format, + int *pdmv, + int *pmvscale, + int *pdct_type) +{ + int mb_type; + int stwtype, stwcode, stwclass; + int motion_type = 0, mv_count, mv_format, dmv, mvscale; + int dct_type; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + static unsigned char stwc_table[3][4] + = { {6,3,7,4}, {2,1,5,4}, {2,5,7,4} }; + static unsigned char stwclass_table[9] + = {0, 1, 2, 1, 1, 2, 3, 3, 4}; + +/* get macroblock_type */ + mb_type = mpeg3video_get_mb_type(slice, video); + + if(slice->fault) return 1; + +/* get spatial_temporal_weight_code */ + if(mb_type & MB_WEIGHT) + { + if(video->stwc_table_index == 0) + stwtype = 4; + else + { + stwcode = mpeg3slice_getbits2(slice_buffer); + stwtype = stwc_table[video->stwc_table_index - 1][stwcode]; + } + } + else + stwtype = (mb_type & MB_CLASS4) ? 8 : 0; + +/* derive spatial_temporal_weight_class (Table 7-18) */ + stwclass = stwclass_table[stwtype]; + +/* get frame/field motion type */ + if(mb_type & (MB_FORWARD | MB_BACKWARD)) + { + if(video->pict_struct == FRAME_PICTURE) + { +/* frame_motion_type */ + motion_type = video->frame_pred_dct ? MC_FRAME : mpeg3slice_getbits2(slice_buffer); + } + else + { +/* field_motion_type */ + motion_type = mpeg3slice_getbits2(slice_buffer); + } + } + else + if((mb_type & MB_INTRA) && video->conceal_mv) + { +/* concealment motion vectors */ + motion_type = (video->pict_struct == FRAME_PICTURE) ? MC_FRAME : MC_FIELD; + } + +/* derive mv_count, mv_format and dmv, (table 6-17, 6-18) */ + if(video->pict_struct == FRAME_PICTURE) + { + mv_count = (motion_type == MC_FIELD && stwclass < 2) ? 2 : 1; + mv_format = (motion_type == MC_FRAME) ? MV_FRAME : MV_FIELD; + } + else + { + mv_count = (motion_type == MC_16X8) ? 2 : 1; + mv_format = MV_FIELD; + } + + dmv = (motion_type == MC_DMV); /* dual prime */ + +/* field mv predictions in frame pictures have to be scaled */ + mvscale = ((mv_format == MV_FIELD) && (video->pict_struct == FRAME_PICTURE)); + +/* get dct_type (frame DCT / field DCT) */ + dct_type = (video->pict_struct == FRAME_PICTURE) && + (!video->frame_pred_dct) && + (mb_type & (MB_PATTERN | MB_INTRA)) ? + mpeg3slice_getbit(slice_buffer) : 0; + +/* return values */ + *pmb_type = mb_type; + *pstwtype = stwtype; + *pstwclass = stwclass; + *pmotion_type = motion_type; + *pmv_count = mv_count; + *pmv_format = mv_format; + *pdmv = dmv; + *pmvscale = mvscale; + *pdct_type = dct_type; + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/mmxidct.S b/core/multimedia/opieplayer/libmpeg3/video/mmxidct.S new file mode 100644 index 0000000..9c3bebe --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/mmxidct.S @@ -0,0 +1,675 @@ +/* + * the input data is tranposed and each 16 bit element in the 8x8 matrix + * is left aligned: + * for example in 11...1110000 format + * If the iDCT is of I macroblock then 0.5 needs to be added to the;DC Component + * (element[0][0] of the matrix) + */ + +/* extrn re_matrix */ + +/* constants */ + +.data + .align 16 + .type preSC, @object +preSC: .short 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520 + .short 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270 + .short 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906 + .short 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315 + .short 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520 + .short 12873, 17855, 16819, 15137, 25746, 20228, 13933, 7103 + .short 17734, 24598, 23170, 20853, 17734, 13933, 9597, 4892 + .short 18081, 25080, 23624, 21261, 18081, 14206, 9785, 4988 + .size preSC, 128 + .align 8 + .type x0005000200010001, @object + .size x0005000200010001, 8 +x0005000200010001: + .long 0x00010001, 0x00050002 + .align 8 + .type x0040000000000000, @object + .size x0040000000000000, 8 +x0040000000000000: + .long 0, 0x00400000 + .align 8 + .type x5a825a825a825a82, @object + .size x5a825a825a825a82, 8 +x5a825a825a825a82: + .long 0x5a825a82, 0x5a825a82 + .align 8 + .type x539f539f539f539f, @object + .size x539f539f539f539f, 8 +x539f539f539f539f: + .long 0x539f539f, 0x539f539f + .align 8 + .type x4546454645464546, @object + .size x4546454645464546, 8 +x4546454645464546: + .long 0x45464546, 0x45464546 + .align 8 + .type x61f861f861f861f8, @object + .size x61f861f861f861f8, 8 +x61f861f861f861f8: + .long 0x61f861f8, 0x61f861f8 +/* Static variables */ + .align 8 + .type x0, @object + .size x0, 8 +x0: + .long 0, 0 +/* Procedure */ + + + .align 8 +.text + .align 4 +.globl IDCT_mmx + .type IDCT_mmx, @function +IDCT_mmx: + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %ecx + pushl %edx + pushl %esi + pushl %edi + + pushl $0 /* allocate the temp variables */ + pushl $0 + pushl $0 + pushl $0 + pushl $0 + pushl $0 + pushl $0 + pushl $0 + + movl 8(%ebp), %esi /* source matrix */ + leal preSC, %ecx +/* column 0: even part + * use V4, V12, V0, V8 to produce V22..V25 + */ + movq 8*12(%ecx), %mm0 /* maybe the first mul can be done together */ + /* with the dequantization in iHuff module */ + pmulhw 8*12(%esi), %mm0 /* V12 */ + movq 8*4(%ecx), %mm1 + pmulhw 8*4(%esi), %mm1 /* V4 */ + movq (%ecx), %mm3 + psraw $1, %mm0 /* t64=t66 */ + pmulhw (%esi), %mm3 /* V0 */ + movq 8*8(%ecx), %mm5 /* duplicate V4 */ + movq %mm1, %mm2 /* added 11/1/96 */ + pmulhw 8*8(%esi),%mm5 /* V8 */ + psubsw %mm0, %mm1 /* V16 */ + pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V18 */ + paddsw %mm0, %mm2 /* V17 */ + movq %mm2, %mm0 /* duplicate V17 */ + psraw $1, %mm2 /* t75=t82 */ + psraw $2, %mm0 /* t72 */ + movq %mm3, %mm4 /* duplicate V0 */ + paddsw %mm5, %mm3 /* V19 */ + psubsw %mm5, %mm4 /* V20 ;mm5 free */ +/* moved from the block below */ + movq 8*10(%ecx), %mm7 + psraw $1, %mm3 /* t74=t81 */ + movq %mm3, %mm6 /* duplicate t74=t81 */ + psraw $2, %mm4 /* t77=t79 */ + psubsw %mm0, %mm1 /* V21 ; mm0 free */ + paddsw %mm2, %mm3 /* V22 */ + movq %mm1, %mm5 /* duplicate V21 */ + paddsw %mm4, %mm1 /* V23 */ + movq %mm3, 8*4(%esi) /* V22 */ + psubsw %mm5, %mm4 /* V24; mm5 free */ + movq %mm1, 8*12(%esi) /* V23 */ + psubsw %mm2, %mm6 /* V25; mm2 free */ + movq %mm4, (%esi) /* V24 */ +/* keep mm6 alive all along the next block */ + /* movq %mm6, 8*8(%esi) V25 */ +/* column 0: odd part + * use V2, V6, V10, V14 to produce V31, V39, V40, V41 + */ +/* moved above: movq 8*10(%ecx), %mm7 */ + + pmulhw 8*10(%esi), %mm7 /* V10 */ + movq 8*6(%ecx), %mm0 + pmulhw 8*6(%esi), %mm0 /* V6 */ + movq 8*2(%ecx), %mm5 + movq %mm7, %mm3 /* duplicate V10 */ + pmulhw 8*2(%esi), %mm5 /* V2 */ + movq 8*14(%ecx), %mm4 + psubsw %mm0, %mm7 /* V26 */ + pmulhw 8*14(%esi), %mm4 /* V14 */ + paddsw %mm0, %mm3 /* V29 ; free mm0 */ + movq %mm7, %mm1 /* duplicate V26 */ + psraw $1, %mm3 /* t91=t94 */ + pmulhw x539f539f539f539f,%mm7 /* V33 */ + psraw $1, %mm1 /* t96 */ + movq %mm5, %mm0 /* duplicate V2 */ + psraw $2, %mm4 /* t85=t87 */ + paddsw %mm4,%mm5 /* V27 */ + psubsw %mm4, %mm0 /* V28 ; free mm4 */ + movq %mm0, %mm2 /* duplicate V28 */ + psraw $1, %mm5 /* t90=t93 */ + pmulhw x4546454645464546,%mm0 /* V35 */ + psraw $1, %mm2 /* t97 */ + movq %mm5, %mm4 /* duplicate t90=t93 */ + psubsw %mm2, %mm1 /* V32 ; free mm2 */ + pmulhw x61f861f861f861f8,%mm1 /* V36 */ + psllw $1, %mm7 /* t107 */ + paddsw %mm3, %mm5 /* V31 */ + psubsw %mm3, %mm4 /* V30 ; free mm3 */ + pmulhw x5a825a825a825a82,%mm4 /* V34 */ + nop + psubsw %mm1, %mm0 /* V38 */ + psubsw %mm7, %mm1 /* V37 ; free mm7 */ + psllw $1, %mm1 /* t114 */ +/* move from the next block */ + movq %mm6, %mm3 /* duplicate V25 */ +/* move from the next block */ + movq 8*4(%esi), %mm7 /* V22 */ + psllw $1, %mm0 /* t110 */ + psubsw %mm5, %mm0 /* V39 (mm5 needed for next block) */ + psllw $2, %mm4 /* t112 */ +/* moved from the next block */ + movq 8*12(%esi), %mm2 /* V23 */ + psubsw %mm0, %mm4 /* V40 */ + paddsw %mm4, %mm1 /* V41; free mm0 */ +/* moved from the next block */ + psllw $1, %mm2 /* t117=t125 */ +/* column 0: output butterfly */ +/* moved above: + * movq %mm6, %mm3 duplicate V25 + * movq 8*4(%esi), %mm7 V22 + * movq 8*12(%esi), %mm2 V23 + * psllw $1, %mm2 t117=t125 + */ + psubsw %mm1, %mm6 /* tm6 */ + paddsw %mm1, %mm3 /* tm8; free mm1 */ + movq %mm7, %mm1 /* duplicate V22 */ + paddsw %mm5, %mm7 /* tm0 */ + movq %mm3, 8*8(%esi) /* tm8; free mm3 */ + psubsw %mm5, %mm1 /* tm14; free mm5 */ + movq %mm6, 8*6(%esi) /* tm6; free mm6 */ + movq %mm2, %mm3 /* duplicate t117=t125 */ + movq (%esi), %mm6 /* V24 */ + paddsw %mm0, %mm2 /* tm2 */ + movq %mm7, (%esi) /* tm0; free mm7 */ + psubsw %mm0, %mm3 /* tm12; free mm0 */ + movq %mm1, 8*14(%esi) /* tm14; free mm1 */ + psllw $1, %mm6 /* t119=t123 */ + movq %mm2, 8*2(%esi) /* tm2; free mm2 */ + movq %mm6, %mm0 /* duplicate t119=t123 */ + movq %mm3, 8*12(%esi) /* tm12; free mm3 */ + paddsw %mm4, %mm6 /* tm4 */ +/* moved from next block */ + movq 8*5(%ecx), %mm1 + psubsw %mm4, %mm0 /* tm10; free mm4 */ +/* moved from next block */ + pmulhw 8*5(%esi), %mm1 /* V5 */ + movq %mm6, 8*4(%esi) /* tm4; free mm6 */ + movq %mm0, 8*10(%esi) /* tm10; free mm0 */ +/* column 1: even part + * use V5, V13, V1, V9 to produce V56..V59 + */ +/* moved to prev block: + * movq 8*5(%ecx), %mm1 + * pmulhw 8*5(%esi), %mm1 V5 + */ + movq 8*13(%ecx), %mm7 + psllw $1, %mm1 /* t128=t130 */ + pmulhw 8*13(%esi), %mm7 /* V13 */ + movq %mm1, %mm2 /* duplicate t128=t130 */ + movq 8(%ecx), %mm3 + pmulhw 8(%esi), %mm3 /* V1 */ + movq 8*9(%ecx), %mm5 + psubsw %mm7, %mm1 /* V50 */ + pmulhw 8*9(%esi), %mm5 /* V9 */ + paddsw %mm7, %mm2 /* V51 */ + pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V52 */ + movq %mm2, %mm6 /* duplicate V51 */ + psraw $1, %mm2 /* t138=t144 */ + movq %mm3, %mm4 /* duplicate V1 */ + psraw $2, %mm6 /* t136 */ + paddsw %mm5, %mm3 /* V53 */ + psubsw %mm5, %mm4 /* V54 ;mm5 free */ + movq %mm3, %mm7 /* duplicate V53 */ +/* moved from next block */ + movq 8*11(%ecx), %mm0 + psraw $1, %mm4 /* t140=t142 */ + psubsw %mm6, %mm1 /* V55 ; mm6 free */ + paddsw %mm2, %mm3 /* V56 */ + movq %mm4, %mm5 /* duplicate t140=t142 */ + paddsw %mm1, %mm4 /* V57 */ + movq %mm3, 8*5(%esi) /* V56 */ + psubsw %mm1, %mm5 /* V58; mm1 free */ + movq %mm4, 8*13(%esi) /* V57 */ + psubsw %mm2, %mm7 /* V59; mm2 free */ + movq %mm5, 8*9(%esi) /* V58 */ +/* keep mm7 alive all along the next block + * movq %mm7, 8(%esi) V59 + * moved above + * movq 8*11(%ecx), %mm0 + */ + pmulhw 8*11(%esi), %mm0 /* V11 */ + movq 8*7(%ecx), %mm6 + pmulhw 8*7(%esi), %mm6 /* V7 */ + movq 8*15(%ecx), %mm4 + movq %mm0, %mm3 /* duplicate V11 */ + pmulhw 8*15(%esi), %mm4 /* V15 */ + movq 8*3(%ecx), %mm5 + psllw $1, %mm6 /* t146=t152 */ + pmulhw 8*3(%esi), %mm5 /* V3 */ + paddsw %mm6, %mm0 /* V63 */ +/* note that V15 computation has a correction step: + * this is a 'magic' constant that rebiases the results to be closer to the + * expected result. this magic constant can be refined to reduce the error + * even more by doing the correction step in a later stage when the number + * is actually multiplied by 16 + */ + paddw x0005000200010001, %mm4 + psubsw %mm6, %mm3 /* V60 ; free mm6 */ + psraw $1, %mm0 /* t154=t156 */ + movq %mm3, %mm1 /* duplicate V60 */ + pmulhw x539f539f539f539f, %mm1 /* V67 */ + movq %mm5, %mm6 /* duplicate V3 */ + psraw $2, %mm4 /* t148=t150 */ + paddsw %mm4, %mm5 /* V61 */ + psubsw %mm4, %mm6 /* V62 ; free mm4 */ + movq %mm5, %mm4 /* duplicate V61 */ + psllw $1, %mm1 /* t169 */ + paddsw %mm0, %mm5 /* V65 -> result */ + psubsw %mm0, %mm4 /* V64 ; free mm0 */ + pmulhw x5a825a825a825a82, %mm4 /* V68 */ + psraw $1, %mm3 /* t158 */ + psubsw %mm6, %mm3 /* V66 */ + movq %mm5, %mm2 /* duplicate V65 */ + pmulhw x61f861f861f861f8, %mm3 /* V70 */ + psllw $1, %mm6 /* t165 */ + pmulhw x4546454645464546, %mm6 /* V69 */ + psraw $1, %mm2 /* t172 */ +/* moved from next block */ + movq 8*5(%esi), %mm0 /* V56 */ + psllw $1, %mm4 /* t174 */ +/* moved from next block */ + psraw $1, %mm0 /* t177=t188 */ + nop + psubsw %mm3, %mm6 /* V72 */ + psubsw %mm1, %mm3 /* V71 ; free mm1 */ + psubsw %mm2, %mm6 /* V73 ; free mm2 */ +/* moved from next block */ + psraw $1, %mm5 /* t178=t189 */ + psubsw %mm6, %mm4 /* V74 */ +/* moved from next block */ + movq %mm0, %mm1 /* duplicate t177=t188 */ + paddsw %mm4, %mm3 /* V75 */ +/* moved from next block */ + paddsw %mm5, %mm0 /* tm1 */ +/* location + * 5 - V56 + * 13 - V57 + * 9 - V58 + * X - V59, mm7 + * X - V65, mm5 + * X - V73, mm6 + * X - V74, mm4 + * X - V75, mm3 + * free mm0, mm1 & mm2 + * moved above + * movq 8*5(%esi), %mm0 V56 + * psllw $1, %mm0 t177=t188 ! new !! + * psllw $1, %mm5 t178=t189 ! new !! + * movq %mm0, %mm1 duplicate t177=t188 + * paddsw %mm5, %mm0 tm1 + */ + movq 8*13(%esi), %mm2 /* V57 */ + psubsw %mm5, %mm1 /* tm15; free mm5 */ + movq %mm0, 8(%esi) /* tm1; free mm0 */ + psraw $1, %mm7 /* t182=t184 ! new !! */ +/* save the store as used directly in the transpose + * movq %mm1, 120(%esi) tm15; free mm1 + */ + movq %mm7, %mm5 /* duplicate t182=t184 */ + psubsw %mm3, %mm7 /* tm7 */ + paddsw %mm3, %mm5 /* tm9; free mm3 */ + movq 8*9(%esi), %mm0 /* V58 */ + movq %mm2, %mm3 /* duplicate V57 */ + movq %mm7, 8*7(%esi) /* tm7; free mm7 */ + psubsw %mm6, %mm3 /* tm13 */ + paddsw %mm6, %mm2 /* tm3 ; free mm6 */ +/* moved up from the transpose */ + movq %mm3, %mm7 +/* moved up from the transpose */ + punpcklwd %mm1, %mm3 + movq %mm0, %mm6 /* duplicate V58 */ + movq %mm2, 8*3(%esi) /* tm3; free mm2 */ + paddsw %mm4, %mm0 /* tm5 */ + psubsw %mm4, %mm6 /* tm11; free mm4 */ +/* moved up from the transpose */ + punpckhwd %mm1, %mm7 + movq %mm0, 8*5(%esi) /* tm5; free mm0 */ +/* moved up from the transpose */ + movq %mm5, %mm2 +/* transpose - M4 part + * --------- --------- + * | M1 | M2 | | M1'| M3'| + * --------- --> --------- + * | M3 | M4 | | M2'| M4'| + * --------- --------- + * Two alternatives: use full mmword approach so the following code can be + * scheduled before the transpose is done without stores, or use the faster + * half mmword stores (when possible) + */ + movd %mm3, 8*9+4(%esi) /* MS part of tmt9 */ + punpcklwd %mm6, %mm5 + movd %mm7, 8*13+4(%esi) /* MS part of tmt13 */ + punpckhwd %mm6, %mm2 + movd %mm5, 8*9(%esi) /* LS part of tmt9 */ + punpckhdq %mm3, %mm5 /* free mm3 */ + movd %mm2, 8*13(%esi) /* LS part of tmt13 */ + punpckhdq %mm7, %mm2 /* free mm7 */ +/* moved up from the M3 transpose */ + movq 8*8(%esi), %mm0 +/* moved up from the M3 transpose */ + movq 8*10(%esi), %mm1 +/* moved up from the M3 transpose */ + movq %mm0, %mm3 +/* shuffle the rest of the data, and write it with 2 mmword writes */ + movq %mm5, 8*11(%esi) /* tmt11 */ +/* moved up from the M3 transpose */ + punpcklwd %mm1, %mm0 + movq %mm2, 8*15(%esi) /* tmt15 */ +/* moved up from the M3 transpose */ + punpckhwd %mm1, %mm3 +/* transpose - M3 part + * moved up to previous code section + * movq 8*8(%esi), %mm0 + * movq 8*10(%esi), %mm1 + * movq %mm0, %mm3 + * punpcklwd %mm1, %mm0 + * punpckhwd %mm1, %mm3 + */ + movq 8*12(%esi), %mm6 + movq 8*14(%esi), %mm4 + movq %mm6, %mm2 +/* shuffle the data and write the lower parts of the transposed in 4 dwords */ + punpcklwd %mm4, %mm6 + movq %mm0, %mm1 + punpckhdq %mm6, %mm1 + movq %mm3, %mm7 + punpckhwd %mm4, %mm2 /* free mm4 */ + punpckldq %mm6, %mm0 /* free mm6 */ +/* moved from next block */ + movq 8*13(%esi), %mm4 /* tmt13 */ + punpckldq %mm2, %mm3 + punpckhdq %mm2, %mm7 /* free mm2 */ +/* moved from next block */ + movq %mm3, %mm5 /* duplicate tmt5 */ +/* column 1: even part (after transpose) +* moved above +* movq %mm3, %mm5 duplicate tmt5 +* movq 8*13(%esi), %mm4 tmt13 +*/ + psubsw %mm4, %mm3 /* V134 */ + pmulhw x5a825a825a825a82, %mm3 /* 23170 ->V136 */ + movq 8*9(%esi), %mm6 /* tmt9 */ + paddsw %mm4, %mm5 /* V135 ; mm4 free */ + movq %mm0, %mm4 /* duplicate tmt1 */ + paddsw %mm6, %mm0 /* V137 */ + psubsw %mm6, %mm4 /* V138 ; mm6 free */ + psllw $2, %mm3 /* t290 */ + psubsw %mm5, %mm3 /* V139 */ + movq %mm0, %mm6 /* duplicate V137 */ + paddsw %mm5, %mm0 /* V140 */ + movq %mm4, %mm2 /* duplicate V138 */ + paddsw %mm3, %mm2 /* V141 */ + psubsw %mm3, %mm4 /* V142 ; mm3 free */ + movq %mm0, 8*9(%esi) /* V140 */ + psubsw %mm5, %mm6 /* V143 ; mm5 free */ +/* moved from next block */ + movq 8*11(%esi), %mm0 /* tmt11 */ + movq %mm2, 8*13(%esi) /* V141 */ +/* moved from next block */ + movq %mm0, %mm2 /* duplicate tmt11 */ +/* column 1: odd part (after transpose) */ +/* moved up to the prev block + * movq 8*11(%esi), %mm0 tmt11 + * movq %mm0, %mm2 duplicate tmt11 + */ + movq 8*15(%esi), %mm5 /* tmt15 */ + psubsw %mm7, %mm0 /* V144 */ + movq %mm0, %mm3 /* duplicate V144 */ + paddsw %mm7, %mm2 /* V147 ; free mm7 */ + pmulhw x539f539f539f539f, %mm0 /* 21407-> V151 */ + movq %mm1, %mm7 /* duplicate tmt3 */ + paddsw %mm5, %mm7 /* V145 */ + psubsw %mm5, %mm1 /* V146 ; free mm5 */ + psubsw %mm1, %mm3 /* V150 */ + movq %mm7, %mm5 /* duplicate V145 */ + pmulhw x4546454645464546, %mm1 /* 17734-> V153 */ + psubsw %mm2, %mm5 /* V148 */ + pmulhw x61f861f861f861f8, %mm3 /* 25080-> V154 */ + psllw $2, %mm0 /* t311 */ + pmulhw x5a825a825a825a82, %mm5 /* 23170-> V152 */ + paddsw %mm2, %mm7 /* V149 ; free mm2 */ + psllw $1, %mm1 /* t313 */ + nop /* without the nop - freeze here for one clock */ + movq %mm3, %mm2 /* duplicate V154 */ + psubsw %mm0, %mm3 /* V155 ; free mm0 */ + psubsw %mm2, %mm1 /* V156 ; free mm2 */ +/* moved from the next block */ + movq %mm6, %mm2 /* duplicate V143 */ +/* moved from the next block */ + movq 8*13(%esi), %mm0 /* V141 */ + psllw $1, %mm1 /* t315 */ + psubsw %mm7, %mm1 /* V157 (keep V149) */ + psllw $2, %mm5 /* t317 */ + psubsw %mm1, %mm5 /* V158 */ + psllw $1, %mm3 /* t319 */ + paddsw %mm5, %mm3 /* V159 */ +/* column 1: output butterfly (after transform) + * moved to the prev block + * movq %mm6, %mm2 duplicate V143 + * movq 8*13(%esi), %mm0 V141 + */ + psubsw %mm3, %mm2 /* V163 */ + paddsw %mm3, %mm6 /* V164 ; free mm3 */ + movq %mm4, %mm3 /* duplicate V142 */ + psubsw %mm5, %mm4 /* V165 ; free mm5 */ + movq %mm2, (%esp) /* out7 */ + psraw $4, %mm6 + psraw $4, %mm4 + paddsw %mm5, %mm3 /* V162 */ + movq 8*9(%esi), %mm2 /* V140 */ + movq %mm0, %mm5 /* duplicate V141 */ +/* in order not to perculate this line up, + * we read 72(%esi) very near to this location + */ + movq %mm6, 8*9(%esi) /* out9 */ + paddsw %mm1, %mm0 /* V161 */ + movq %mm3, 8(%esp) /* out5 */ + psubsw %mm1, %mm5 /* V166 ; free mm1 */ + movq %mm4, 8*11(%esi) /* out11 */ + psraw $4, %mm5 + movq %mm0, 16(%esp) /* out3 */ + movq %mm2, %mm4 /* duplicate V140 */ + movq %mm5, 8*13(%esi) /* out13 */ + paddsw %mm7, %mm2 /* V160 */ +/* moved from the next block */ + movq 8(%esi), %mm0 + psubsw %mm7, %mm4 /* V167 ; free mm7 */ +/* moved from the next block */ + movq 8*3(%esi), %mm7 + psraw $4, %mm4 + movq %mm2, 24(%esp) /* out1 */ +/* moved from the next block */ + movq %mm0, %mm1 + movq %mm4, 8*15(%esi) /* out15 */ +/* moved from the next block */ + punpcklwd %mm7, %mm0 +/* transpose - M2 parts + * moved up to the prev block + * movq 8(%esi), %mm0 + * movq 8*3(%esi), %mm7 + * movq %mm0, %mm1 + * punpcklwd %mm7, %mm0 + */ + movq 8*5(%esi), %mm5 + punpckhwd %mm7, %mm1 + movq 8*7(%esi), %mm4 + movq %mm5, %mm3 +/* shuffle the data and write the lower parts of the trasposed in 4 dwords */ + movd %mm0, 8*8(%esi) /* LS part of tmt8 */ + punpcklwd %mm4, %mm5 + movd %mm1, 8*12(%esi) /* LS part of tmt12 */ + punpckhwd %mm4, %mm3 + movd %mm5, 8*8+4(%esi) /* MS part of tmt8 */ + punpckhdq %mm5, %mm0 /* tmt10 */ + movd %mm3, 8*12+4(%esi) /* MS part of tmt12 */ + punpckhdq %mm3, %mm1 /* tmt14 */ +/* transpose - M1 parts */ + movq (%esi), %mm7 + movq 8*2(%esi), %mm2 + movq %mm7, %mm6 + movq 8*4(%esi), %mm5 + punpcklwd %mm2, %mm7 + movq 8*6(%esi), %mm4 + punpckhwd %mm2, %mm6 /* free mm2 */ + movq %mm5, %mm3 + punpcklwd %mm4, %mm5 + punpckhwd %mm4, %mm3 /* free mm4 */ + movq %mm7, %mm2 + movq %mm6, %mm4 + punpckldq %mm5, %mm7 /* tmt0 */ + punpckhdq %mm5, %mm2 /* tmt2 ; free mm5 */ +/* shuffle the rest of the data, and write it with 2 mmword writes */ + punpckldq %mm3, %mm6 /* tmt4 */ +/* moved from next block */ + movq %mm2, %mm5 /* duplicate tmt2 */ + punpckhdq %mm3, %mm4 /* tmt6 ; free mm3 */ +/* moved from next block */ + movq %mm0, %mm3 /* duplicate tmt10 */ +/* column 0: odd part (after transpose) + *moved up to prev block + * movq %mm0, %mm3 duplicate tmt10 + * movq %mm2, %mm5 duplicate tmt2 + */ + psubsw %mm4, %mm0 /* V110 */ + paddsw %mm4, %mm3 /* V113 ; free mm4 */ + movq %mm0, %mm4 /* duplicate V110 */ + paddsw %mm1, %mm2 /* V111 */ + pmulhw x539f539f539f539f, %mm0 /* 21407-> V117 */ + psubsw %mm1, %mm5 /* V112 ; free mm1 */ + psubsw %mm5, %mm4 /* V116 */ + movq %mm2, %mm1 /* duplicate V111 */ + pmulhw x4546454645464546, %mm5 /* 17734-> V119 */ + psubsw %mm3, %mm2 /* V114 */ + pmulhw x61f861f861f861f8, %mm4 /* 25080-> V120 */ + paddsw %mm3, %mm1 /* V115 ; free mm3 */ + pmulhw x5a825a825a825a82, %mm2 /* 23170-> V118 */ + psllw $2, %mm0 /* t266 */ + movq %mm1, (%esi) /* save V115 */ + psllw $1, %mm5 /* t268 */ + psubsw %mm4, %mm5 /* V122 */ + psubsw %mm0, %mm4 /* V121 ; free mm0 */ + psllw $1, %mm5 /* t270 */ + psubsw %mm1, %mm5 /* V123 ; free mm1 */ + psllw $2, %mm2 /* t272 */ + psubsw %mm5, %mm2 /* V124 (keep V123) */ + psllw $1, %mm4 /* t274 */ + movq %mm5, 8*2(%esi) /* save V123 ; free mm5 */ + paddsw %mm2, %mm4 /* V125 (keep V124) */ +/* column 0: even part (after transpose) */ + movq 8*12(%esi), %mm0 /* tmt12 */ + movq %mm6, %mm3 /* duplicate tmt4 */ + psubsw %mm0, %mm6 /* V100 */ + paddsw %mm0, %mm3 /* V101 ; free mm0 */ + pmulhw x5a825a825a825a82, %mm6 /* 23170 ->V102 */ + movq %mm7, %mm5 /* duplicate tmt0 */ + movq 8*8(%esi), %mm1 /* tmt8 */ + paddsw %mm1, %mm7 /* V103 */ + psubsw %mm1, %mm5 /* V104 ; free mm1 */ + movq %mm7, %mm0 /* duplicate V103 */ + psllw $2, %mm6 /* t245 */ + paddsw %mm3, %mm7 /* V106 */ + movq %mm5, %mm1 /* duplicate V104 */ + psubsw %mm3, %mm6 /* V105 */ + psubsw %mm3, %mm0 /* V109; free mm3 */ + paddsw %mm6, %mm5 /* V107 */ + psubsw %mm6, %mm1 /* V108 ; free mm6 */ +/* column 0: output butterfly (after transform) */ + movq %mm1, %mm3 /* duplicate V108 */ + paddsw %mm2, %mm1 /* out4 */ + psraw $4, %mm1 + psubsw %mm2, %mm3 /* out10 ; free mm2 */ + psraw $4, %mm3 + movq %mm0, %mm6 /* duplicate V109 */ + movq %mm1, 8*4(%esi) /* out4 ; free mm1 */ + psubsw %mm4, %mm0 /* out6 */ + movq %mm3, 8*10(%esi) /* out10 ; free mm3 */ + psraw $4, %mm0 + paddsw %mm4, %mm6 /* out8 ; free mm4 */ + movq %mm7, %mm1 /* duplicate V106 */ + movq %mm0, 8*6(%esi) /* out6 ; free mm0 */ + psraw $4, %mm6 + movq (%esi), %mm4 /* V115 */ + movq %mm6, 8*8(%esi) /* out8 ; free mm6 */ + movq %mm5, %mm2 /* duplicate V107 */ + movq 8*2(%esi), %mm3 /* V123 */ + paddsw %mm4, %mm7 /* out0 */ +/* moved up from next block */ + movq 16(%esp), %mm0 + psraw $4, %mm7 +/* moved up from next block */ + movq 8(%esp), %mm6 + psubsw %mm4, %mm1 /* out14 ; free mm4 */ + paddsw %mm3, %mm5 /* out2 */ + psraw $4, %mm1 + movq %mm7, (%esi) /* out0 ; free mm7 */ + psraw $4, %mm5 + movq %mm1, 8*14(%esi) /* out14 ; free mm1 */ + psubsw %mm3, %mm2 /* out12 ; free mm3 */ + movq %mm5, 8*2(%esi) /* out2 ; free mm5 */ + psraw $4, %mm2 +/* moved up to the prev block */ + movq (%esp), %mm4 +/* moved up to the prev block */ + psraw $4, %mm0 + movq %mm2, 8*12(%esi) /* out12 ; free mm2 */ +/* moved up to the prev block */ + psraw $4, %mm6 +/* move back the data to its correct place +* moved up to the prev block + * movq 16(%esp), %mm0 + * movq 8(%esp), %mm6 + * movq (%esp), %mm4 + * psraw $4, %mm0 + * psraw $4, %mm6 +*/ + movq 24(%esp), %mm1 + psraw $4, %mm4 + movq %mm0, 8*3(%esi) /* out3 */ + psraw $4, %mm1 + movq %mm6, 8*5(%esi) /* out5 */ + movq %mm4, 8*7(%esi) /* out7 */ + movq %mm1, 8(%esi) /* out1 */ + + popl %edi /* Pop off the temp variables */ + popl %edi + popl %edi + popl %edi + popl %edi + popl %edi + popl %edi + popl %edi + + popl %edi /* Pop off the old variables */ + popl %esi + popl %edx + popl %ecx + popl %ebx + movl %ebp, %esp + popl %ebp + + ret +.Lfe1: + .size IDCT_mmx,.Lfe1-IDCT_mmx diff --git a/core/multimedia/opieplayer/libmpeg3/video/mmxtest.c b/core/multimedia/opieplayer/libmpeg3/video/mmxtest.c new file mode 100644 index 0000000..567f139 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/mmxtest.c @@ -0,0 +1,35 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" + +#include +#include + +int mpeg3_mmx_test() +{ + int result = 0; + FILE *proc; + char string[MPEG3_STRLEN]; + + +#ifdef HAVE_MMX + if(!(proc = fopen(MPEG3_PROC_CPUINFO, "r"))) + { + return 0; + } + + while(!feof(proc)) + { + fgets(string, MPEG3_STRLEN, proc); +/* Got the flags line */ + if(!strncmp(string, "flags", 5)) + { + char *needle; + needle = strstr(string, "mmx"); + if(!needle) return 0; + if(!strncmp(needle, "mmx", 3)) return 1; + } + } +#endif + + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/motion.c b/core/multimedia/opieplayer/libmpeg3/video/motion.c new file mode 100644 index 0000000..4d2f681 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/motion.c @@ -0,0 +1,230 @@ +#include "mpeg3video.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "vlc.h" + +#include + + +/* calculate motion vector component */ + +static inline void mpeg3video_calc_mv(int *pred, int r_size, int motion_code, int motion_r, int full_pel_vector) +{ + int lim = 16 << r_size; + int vec = full_pel_vector ? (*pred >> 1) : (*pred); + + if(motion_code > 0) + { + vec += ((motion_code - 1) << r_size) + motion_r + 1; + if(vec >= lim) vec -= lim + lim; + } + else + if(motion_code < 0) + { + vec -= ((-motion_code - 1) << r_size) + motion_r + 1; + if(vec < -lim) vec += lim + lim; + } + *pred = full_pel_vector ? (vec << 1) : vec; +} + + +/* +int *dmvector, * differential motion vector * +int mvx, int mvy * decoded mv components (always in field format) * +*/ +void mpeg3video_calc_dmv(mpeg3video_t *video, + int DMV[][2], + int *dmvector, + int mvx, + int mvy) +{ + if(video->pict_struct == FRAME_PICTURE) + { + if(video->topfirst) + { +/* vector for prediction of top field from bottom field */ + DMV[0][0] = ((mvx + (mvx>0)) >> 1) + dmvector[0]; + DMV[0][1] = ((mvy + (mvy>0)) >> 1) + dmvector[1] - 1; + +/* vector for prediction of bottom field from top field */ + DMV[1][0] = ((3 * mvx + (mvx > 0)) >> 1) + dmvector[0]; + DMV[1][1] = ((3 * mvy + (mvy > 0)) >> 1) + dmvector[1] + 1; + } + else + { +/* vector for prediction of top field from bottom field */ + DMV[0][0] = ((3 * mvx + (mvx>0)) >> 1) + dmvector[0]; + DMV[0][1] = ((3 * mvy + (mvy>0)) >> 1) + dmvector[1] - 1; + +/* vector for prediction of bottom field from top field */ + DMV[1][0] = ((mvx + (mvx>0)) >> 1) + dmvector[0]; + DMV[1][1] = ((mvy + (mvy>0)) >> 1) + dmvector[1] + 1; + } + } + else + { +/* vector for prediction from field of opposite 'parity' */ + DMV[0][0] = ((mvx + (mvx > 0)) >> 1) + dmvector[0]; + DMV[0][1] = ((mvy + (mvy > 0)) >> 1) + dmvector[1]; + +/* correct for vertical field shift */ + if(video->pict_struct == TOP_FIELD) + DMV[0][1]--; + else + DMV[0][1]++; + } +} + +static inline int mpeg3video_get_mv(mpeg3_slice_t *slice) +{ + int code; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + if(mpeg3slice_getbit(slice_buffer)) + { + return 0; + } + + if((code = mpeg3slice_showbits9(slice_buffer)) >= 64) + { + code >>= 6; + mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab0[code].len); + return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab0[code].val : mpeg3_MVtab0[code].val; + } + + if(code >= 24) + { + code >>= 3; + mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab1[code].len); + return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab1[code].val : mpeg3_MVtab1[code].val; + } + + if((code -= 12) < 0) + { +/* fprintf(stdout,"mpeg3video_get_mv: invalid motion_vector code\n"); */ + slice->fault = 1; + return 1; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab2[code].len); + return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab2[code].val : mpeg3_MVtab2[code].val; +} + +/* get differential motion vector (for dual prime prediction) */ + +static inline int mpeg3video_get_dmv(mpeg3_slice_t *slice) +{ + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + if(mpeg3slice_getbit(slice_buffer)) + { + return mpeg3slice_getbit(slice_buffer) ? -1 : 1; + } + else + { + return 0; + } +} + + + +/* get and decode motion vector and differential motion vector */ + +void mpeg3video_motion_vector(mpeg3_slice_t *slice, + mpeg3video_t *video, + int *PMV, + int *dmvector, + int h_r_size, + int v_r_size, + int dmv, + int mvscale, + int full_pel_vector) +{ + int motion_r; + int motion_code = mpeg3video_get_mv(slice); + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + if(slice->fault) return; + motion_r = (h_r_size != 0 && motion_code != 0) ? mpeg3slice_getbits(slice_buffer, h_r_size) : 0; + + mpeg3video_calc_mv(&PMV[0], h_r_size, motion_code, motion_r, full_pel_vector); + + if(dmv) dmvector[0] = mpeg3video_get_dmv(slice); + + motion_code = mpeg3video_get_mv(slice); + if(slice->fault) return; + motion_r = (v_r_size != 0 && motion_code != 0) ? mpeg3slice_getbits(slice_buffer, v_r_size) : 0; + +/* DIV 2 */ + if(mvscale) PMV[1] >>= 1; + + mpeg3video_calc_mv(&PMV[1], v_r_size, motion_code, motion_r, full_pel_vector); + + if(mvscale) PMV[1] <<= 1; + if(dmv) dmvector[1] = mpeg3video_get_dmv(slice); +} + +int mpeg3video_motion_vectors(mpeg3_slice_t *slice, + mpeg3video_t *video, + int PMV[2][2][2], + int dmvector[2], + int mv_field_sel[2][2], + int s, + int mv_count, + int mv_format, + int h_r_size, + int v_r_size, + int dmv, + int mvscale) +{ + int result = 0; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + if(mv_count == 1) + { + if(mv_format == MV_FIELD && !dmv) + { + mv_field_sel[1][s] = mv_field_sel[0][s] = mpeg3slice_getbit(slice_buffer); + } + + mpeg3video_motion_vector(slice, + video, + PMV[0][s], + dmvector, + h_r_size, + v_r_size, + dmv, + mvscale, + 0); + if(slice->fault) return 1; + +/* update other motion vector predictors */ + PMV[1][s][0] = PMV[0][s][0]; + PMV[1][s][1] = PMV[0][s][1]; + } + else + { + mv_field_sel[0][s] = mpeg3slice_getbit(slice_buffer); + mpeg3video_motion_vector(slice, + video, + PMV[0][s], + dmvector, + h_r_size, + v_r_size, + dmv, + mvscale, + 0); + if(slice->fault) return 1; + + mv_field_sel[1][s] = mpeg3slice_getbit(slice_buffer); + mpeg3video_motion_vector(slice, + video, + PMV[1][s], + dmvector, + h_r_size, + v_r_size, + dmv, + mvscale, + 0); + if(slice->fault) return 1; + } + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c b/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c new file mode 100644 index 0000000..a9f113e --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c @@ -0,0 +1,597 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include "mpeg3videoprotos.h" +#include + +unsigned char mpeg3_zig_zag_scan_mmx[64] = +{ + 0*8+0 /* 0*/, 1*8+0 /* 1*/, 0*8+1 /* 8*/, 0*8+2 /*16*/, 1*8+1 /* 9*/, 2*8+0 /* 2*/, 3*8+0 /* 3*/, 2*8+1 /*10*/, + 1*8+2 /*17*/, 0*8+3 /*24*/, 0*8+4 /*32*/, 1*8+3 /*25*/, 2*8+2 /*18*/, 3*8+1 /*11*/, 4*8+0 /* 4*/, 5*8+0 /* 5*/, + 4*8+1 /*12*/, 5*8+2 /*19*/, 2*8+3 /*26*/, 1*8+4 /*33*/, 0*8+5 /*40*/, 0*8+6 /*48*/, 1*8+5 /*41*/, 2*8+4 /*34*/, + 3*8+3 /*27*/, 4*8+2 /*20*/, 5*8+1 /*13*/, 6*8+0 /* 6*/, 7*8+0 /* 7*/, 6*8+1 /*14*/, 5*8+2 /*21*/, 4*8+3 /*28*/, + 3*8+4 /*35*/, 2*8+5 /*42*/, 1*8+6 /*49*/, 0*8+7 /*56*/, 1*8+7 /*57*/, 2*8+6 /*50*/, 3*8+5 /*43*/, 4*8+4 /*36*/, + 5*8+3 /*29*/, 6*8+2 /*22*/, 7*8+1 /*15*/, 7*8+2 /*23*/, 6*8+3 /*30*/, 5*8+4 /*37*/, 4*8+5 /*44*/, 3*8+6 /*51*/, + 2*8+7 /*58*/, 3*8+7 /*59*/, 4*8+6 /*52*/, 5*8+5 /*45*/, 6*8+4 /*38*/, 7*8+3 /*31*/, 7*8+4 /*39*/, 6*8+5 /*46*/, + 7*8+6 /*53*/, 4*8+7 /*60*/, 5*8+7 /*61*/, 6*8+6 /*54*/, 7*8+5 /*47*/, 7*8+6 /*55*/, 6*8+7 /*62*/, 7*8+7 /*63*/ +}; + +/* alternate scan */ +unsigned char mpeg3_alternate_scan_mmx[64] = +{ + 0*8+0 /*0 */, 0*8+1 /* 8*/, 0*8+2 /*16*/, 0*8+3 /*24*/, 1*8+0 /* 1*/, 1*8+1 /* 9*/, 2*8+0 /* 2*/, 2*8+1 /*10*/, + 1*8+2 /*17*/, 1*8+3 /*25*/, 0*8+4 /*32*/, 0*8+5 /*40*/, 0*8+6 /*48*/, 0*8+7 /*56*/, 1*8+7 /*57*/, 1*8+6 /*49*/, + 1*8+5 /*41*/, 1*8+4 /*33*/, 2*8+3 /*26*/, 2*8+2 /*18*/, 3*8+0 /* 3*/, 3*8+1 /*11*/, 4*8+0 /* 4*/, 4*8+1 /*12*/, + 3*8+2 /*19*/, 3*8+3 /*27*/, 2*8+4 /*34*/, 2*8+5 /*42*/, 2*8+6 /*50*/, 2*8+7 /*58*/, 3*8+4 /*35*/, 3*8+5 /*43*/, + 3*8+6 /*51*/, 3*8+7 /*59*/, 4*8+2 /*20*/, 4*8+3 /*28*/, 5*8+0 /* 5*/, 5*8+1 /*13*/, 6*8+0 /* 6*/, 6*8+1 /*14*/, + 5*8+2 /*21*/, 5*8+3 /*29*/, 4*8+4 /*36*/, 4*8+5 /*44*/, 4*8+6 /*52*/, 4*8+7 /*60*/, 5*8+4 /*37*/, 5*8+5 /*45*/, + 5*8+6 /*53*/, 5*8+7 /*61*/, 6*8+2 /*22*/, 6*8+3 /*30*/, 7*8+0 /* 7*/, 7*8+1 /*15*/, 7*8+2 /*23*/, 7*8+3 /*31*/, + 6*8+4 /*38*/, 6*8+5 /*46*/, 6*8+6 /*54*/, 6*8+7 /*62*/, 7*8+4 /*39*/, 7*8+5 /*47*/, 7*8+6 /*55*/, 7*8+6 /*63*/ +}; + + + +/* zig-zag scan */ +unsigned char mpeg3_zig_zag_scan_nommx[64] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +/* alternate scan */ +unsigned char mpeg3_alternate_scan_nommx[64] = +{ + 0, 8, 16, 24, 1, 9, 2, 10, 17, 25, 32, 40, 48, 56, 57, 49, + 41, 33, 26, 18, 3, 11, 4, 12, 19, 27, 34, 42, 50, 58, 35, 43, + 51, 59, 20, 28, 5, 13, 6, 14, 21, 29, 36, 44, 52, 60, 37, 45, + 53, 61, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63 +}; + +/* default intra quantization matrix */ +unsigned char mpeg3_default_intra_quantizer_matrix[64] = +{ + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 22, 24, 27, 29, 34, 37, + 19, 22, 26, 27, 29, 34, 34, 38, + 22, 22, 26, 27, 29, 34, 37, 40, + 22, 26, 27, 29, 32, 35, 40, 48, + 26, 27, 29, 32, 35, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83 +}; + +unsigned char mpeg3_non_linear_mquant_table[32] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 10, 12, 14, 16, 18, 20, 22, + 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 96, 104, 112 +}; + +double mpeg3_frame_rate_table[16] = +{ + 0.0, /* Pad */ + 24000.0/1001.0, /* Official frame rates */ + 24.0, + 25.0, + 30000.0/1001.0, + 30.0, + 50.0, + ((60.0*1000.0)/1001.0), + 60.0, + + 1, /* Unofficial economy rates */ + 5, + 10, + 12, + 15, + 0, + 0, +}; + +int mpeg3video_initdecoder(mpeg3video_t *video) +{ + int blk_cnt_tab[3] = {6, 8, 12}; + int cc; + int i; + long size[4], padding[2]; /* Size of Y, U, and V buffers */ + + if(!video->mpeg2) + { +/* force MPEG-1 parameters */ + video->prog_seq = 1; + video->prog_frame = 1; + video->pict_struct = FRAME_PICTURE; + video->frame_pred_dct = 1; + video->chroma_format = CHROMA420; + video->matrix_coefficients = 5; + } + +/* Get dimensions rounded to nearest multiple of coded macroblocks */ + video->mb_width = (video->horizontal_size + 15) / 16; + video->mb_height = (video->mpeg2 && !video->prog_seq) ? + (2 * ((video->vertical_size + 31) / 32)) : + ((video->vertical_size + 15) / 16); + video->coded_picture_width = 16 * video->mb_width; + video->coded_picture_height = 16 * video->mb_height; + video->chrom_width = (video->chroma_format == CHROMA444) ? + video->coded_picture_width : + (video->coded_picture_width >> 1); + video->chrom_height = (video->chroma_format != CHROMA420) ? + video->coded_picture_height : + (video->coded_picture_height >> 1); + video->blk_cnt = blk_cnt_tab[video->chroma_format - 1]; + +/* Get sizes of YUV buffers */ + padding[0] = 16 * video->coded_picture_width; + size[0] = video->coded_picture_width * video->coded_picture_height + padding[0] * 2; + + padding[1] = 16 * video->chrom_width; + size[1] = video->chrom_width * video->chrom_height + 2 * padding[1]; + + size[2] = (video->llw * video->llh); + size[3] = (video->llw * video->llh) / 4; + +/* Allocate contiguous fragments for YUV buffers for hardware YUV decoding */ + video->yuv_buffer[0] = (unsigned char*)calloc(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); + video->yuv_buffer[1] = (unsigned char*)calloc(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); + video->yuv_buffer[2] = (unsigned char*)calloc(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); + + if(video->scalable_mode == SC_SPAT) + { + video->yuv_buffer[3] = (unsigned char*)calloc(1, size[2] + 2 * size[3]); + video->yuv_buffer[4] = (unsigned char*)calloc(1, size[2] + 2 * size[3]); + } + +/* Direct pointers to areas of contiguous fragments in YVU order per Microsoft */ + for(cc = 0; cc < 3; cc++) + { + video->llframe0[cc] = 0; + video->llframe1[cc] = 0; + video->newframe[cc] = 0; + } + + video->refframe[0] = video->yuv_buffer[0]; + video->oldrefframe[0] = video->yuv_buffer[1]; + video->auxframe[0] = video->yuv_buffer[2]; + video->refframe[2] = video->yuv_buffer[0] + size[0] + padding[0]; + video->oldrefframe[2] = video->yuv_buffer[1] + size[0] + padding[0]; + video->auxframe[2] = video->yuv_buffer[2] + size[0] + padding[0]; + video->refframe[1] = video->yuv_buffer[0] + size[0] + padding[0] + size[1] + padding[1]; + video->oldrefframe[1] = video->yuv_buffer[1] + size[0] + padding[0] + size[1] + padding[1]; + video->auxframe[1] = video->yuv_buffer[2] + size[0] + padding[0] + size[1] + padding[1]; + + if(video->scalable_mode == SC_SPAT) + { +/* this assumes lower layer is 4:2:0 */ + video->llframe0[0] = video->yuv_buffer[3] + padding[0] ; + video->llframe1[0] = video->yuv_buffer[4] + padding[0] ; + video->llframe0[2] = video->yuv_buffer[3] + padding[1] + size[2] ; + video->llframe1[2] = video->yuv_buffer[4] + padding[1] + size[2] ; + video->llframe0[1] = video->yuv_buffer[3] + padding[1] + size[2] + size[3]; + video->llframe1[1] = video->yuv_buffer[4] + padding[1] + size[2] + size[3]; + } + +/* Initialize the YUV tables for software YUV decoding */ + video->cr_to_r = (long*)malloc(sizeof(long) * 256); + video->cr_to_g = (long*)malloc(sizeof(long) * 256); + video->cb_to_g = (long*)malloc(sizeof(long) * 256); + video->cb_to_b = (long*)malloc(sizeof(long) * 256); + video->cr_to_r_ptr = video->cr_to_r + 128; + video->cr_to_g_ptr = video->cr_to_g + 128; + video->cb_to_g_ptr = video->cb_to_g + 128; + video->cb_to_b_ptr = video->cb_to_b + 128; + + for(i = -128; i < 128; i++) + { + video->cr_to_r_ptr[i] = (long)( 1.371 * 65536 * i); + video->cr_to_g_ptr[i] = (long)(-0.698 * 65536 * i); + video->cb_to_g_ptr[i] = (long)(-0.336 * 65536 * i); + video->cb_to_b_ptr[i] = (long)( 1.732 * 65536 * i); + } + + return 0; +} + +int mpeg3video_deletedecoder(mpeg3video_t *video) +{ + int i, padding; + + free(video->yuv_buffer[0]); + free(video->yuv_buffer[1]); + free(video->yuv_buffer[2]); + + if(video->llframe0[0]) + { + free(video->yuv_buffer[3]); + free(video->yuv_buffer[4]); + } + + free(video->cr_to_r); + free(video->cr_to_g); + free(video->cb_to_g); + free(video->cb_to_b); + return 0; +} + +void mpeg3video_init_scantables(mpeg3video_t *video) +{ +#ifdef HAVE_MMX + if(video->have_mmx) + { + video->mpeg3_zigzag_scan_table = mpeg3_zig_zag_scan_mmx; + video->mpeg3_alternate_scan_table = mpeg3_alternate_scan_mmx; + } + else +#endif + { + video->mpeg3_zigzag_scan_table = mpeg3_zig_zag_scan_nommx; + video->mpeg3_alternate_scan_table = mpeg3_alternate_scan_nommx; + } +} + +mpeg3video_t* mpeg3video_allocate_struct(mpeg3_t *file, mpeg3_vtrack_t *track) +{ + int i; + mpeg3video_t *video = (mpeg3video_t*)calloc(1, sizeof(mpeg3video_t)); + pthread_mutexattr_t mutex_attr; + + video->file = file; + video->track = track; + video->vstream = mpeg3bits_new_stream(file, track->demuxer); + video->last_number = -1; + +/* First frame is all green */ + video->framenum = -1; + video->have_mmx = file->have_mmx; + + video->percentage_seek = -1; + video->frame_seek = -1; + + mpeg3video_init_scantables(video); + mpeg3video_init_output(); + + pthread_mutexattr_init(&mutex_attr); + pthread_mutex_init(&(video->test_lock), &mutex_attr); + pthread_mutex_init(&(video->slice_lock), &mutex_attr); + return video; +} + +int mpeg3video_delete_struct(mpeg3video_t *video) +{ + int i; + mpeg3bits_delete_stream(video->vstream); + pthread_mutex_destroy(&(video->test_lock)); + pthread_mutex_destroy(&(video->slice_lock)); + if(video->x_table) + { + free(video->x_table); + free(video->y_table); + } + if(video->total_slice_decoders) + { + for(i = 0; i < video->total_slice_decoders; i++) + mpeg3_delete_slice_decoder(&video->slice_decoders[i]); + } + for(i = 0; i < video->slice_buffers_initialized; i++) + mpeg3_delete_slice_buffer(&(video->slice_buffers[i])); + + free(video); +} + + +int mpeg3video_read_frame_backend(mpeg3video_t *video, int skip_bframes) +{ + int result = 0; + + if(mpeg3bits_eof(video->vstream)) result = 1; + + if(!result) result = mpeg3video_get_header(video, 0); + +//printf("frame type %d\n", video->pict_type); +/* skip_bframes is the number of bframes we can skip successfully. */ +/* This is in case a skipped B-frame is repeated and the second repeat happens */ +/* to be a B frame we need. */ + video->skip_bframes = skip_bframes; + + if(!result) + result = mpeg3video_getpicture(video, video->framenum); + +#ifdef HAVE_MMX + if(video->have_mmx) + __asm__ __volatile__ ("emms"); +#endif + + if(!result) + { + video->last_number = video->framenum; + video->framenum++; + } + return result; +} + +int* mpeg3video_get_scaletable(int input_w, int output_w) +{ + int *result = (int*)malloc(sizeof(int) * output_w); + float i; + float scale = (float)input_w / output_w; + for(i = 0; i < output_w; i++) + { + result[(int)i] = (int)(scale * i); + } + return result; +} + +/* Get the first frame read. */ +int mpeg3video_get_firstframe(mpeg3video_t *video) +{ + int result = 0; + if(video->framenum < 0) + { + video->repeat_count = video->current_repeat = 0; + result = mpeg3video_read_frame_backend(video, 0); + mpeg3bits_seek_byte(video->vstream, 0); + mpeg3video_match_refframes(video); + } + return result; +} + + +/* ======================================================================= */ +/* ENTRY POINTS */ +/* ======================================================================= */ + + + +mpeg3video_t* mpeg3video_new(mpeg3_t *file, mpeg3_vtrack_t *track) +{ + mpeg3video_t *video; + int result = 0; + + video = mpeg3video_allocate_struct(file, track); + result = mpeg3video_get_header(video, 1); + + if(!result) + { + int hour, minute, second, frame; + int gop_found; + + mpeg3video_initdecoder(video); + video->decoder_initted = 1; + track->width = video->horizontal_size; + track->height = video->vertical_size; + track->frame_rate = video->frame_rate; + +/* Get the length of the file from an elementary stream */ + if(file->is_video_stream) + { +/* Load the first GOP */ + mpeg3bits_seek_start(video->vstream); + result = mpeg3video_next_code(video->vstream, MPEG3_GOP_START_CODE); + if(!result) mpeg3bits_getbits(video->vstream, 32); + if(!result) result = mpeg3video_getgophdr(video); + + hour = video->gop_timecode.hour; + minute = video->gop_timecode.minute; + second = video->gop_timecode.second; + frame = video->gop_timecode.frame; + video->first_frame = (long)(hour * 3600 * video->frame_rate + + minute * 60 * video->frame_rate + + second * video->frame_rate + + frame); + +/* GOPs always have 16 frames */ + video->frames_per_gop = 16; + +/* Read the last GOP in the file by seeking backward. */ + mpeg3bits_seek_end(video->vstream); + mpeg3bits_start_reverse(video->vstream); + result = mpeg3video_prev_code(video->vstream, MPEG3_GOP_START_CODE); + mpeg3bits_start_forward(video->vstream); + mpeg3bits_getbits(video->vstream, 8); + if(!result) result = mpeg3video_getgophdr(video); + + hour = video->gop_timecode.hour; + minute = video->gop_timecode.minute; + second = video->gop_timecode.second; + frame = video->gop_timecode.frame; + + video->last_frame = (long)(hour * 3600 * video->frame_rate + + minute * 60 * video->frame_rate + + second * video->frame_rate + + frame); + +/* Count number of frames to end */ + while(!result) + { + result = mpeg3video_next_code(video->vstream, MPEG3_PICTURE_START_CODE); + if(!result) + { + mpeg3bits_getbyte_noptr(video->vstream); + video->last_frame++; + } + } + + track->total_frames = video->last_frame - video->first_frame + 1; + mpeg3bits_seek_start(video->vstream); + } + else + { +/* Gross approximation from a multiplexed file. */ + video->first_frame = 0; + track->total_frames = video->last_frame = + (long)(mpeg3demux_length(video->vstream->demuxer) * + video->frame_rate); + video->first_frame = 0; + } + + video->maxframe = track->total_frames; + mpeg3bits_seek_start(video->vstream); + } + else + { + mpeg3video_delete(video); + video = 0; + } + + return video; +} + +int mpeg3video_delete(mpeg3video_t *video) +{ + if(video->decoder_initted) + { + mpeg3video_deletedecoder(video); + } + mpeg3video_delete_struct(video); + return 0; +} + +int mpeg3video_set_cpus(mpeg3video_t *video, int cpus) +{ + return 0; +} + +int mpeg3video_set_mmx(mpeg3video_t *video, int use_mmx) +{ + video->have_mmx = use_mmx; + mpeg3video_init_scantables(video); + return 0; +} + +int mpeg3video_seek_percentage(mpeg3video_t *video, double percentage) +{ + video->percentage_seek = percentage; + return 0; +} + +int mpeg3video_previous_frame(mpeg3video_t *video) +{ + if(mpeg3bits_tell_percentage(video->vstream) <= 0) return 1; + mpeg3bits_start_reverse(video->vstream); + mpeg3video_prev_code(video->vstream, MPEG3_PICTURE_START_CODE); + mpeg3bits_getbits_reverse(video->vstream, 32); + + if(mpeg3bits_bof(video->vstream)) mpeg3bits_seek_percentage(video->vstream, 0); + mpeg3bits_start_forward(video->vstream); + video->repeat_count = 0; + return 0; +} + +int mpeg3video_seek_frame(mpeg3video_t *video, long frame) +{ + video->frame_seek = frame; + return 0; +} + +/* Read all the way up to and including the next picture start code */ +int mpeg3video_read_raw(mpeg3video_t *video, unsigned char *output, long *size, long max_size) +{ + unsigned MPEG3_INT32 code = 0; + mpeg3_bits_t *vstream = video->vstream; + + *size = 0; + while(code != MPEG3_PICTURE_START_CODE && + code != MPEG3_SEQUENCE_END_CODE && + *size < max_size && + !mpeg3bits_eof(vstream)) + { + code <<= 8; + *output = mpeg3bits_getbyte_noptr(vstream); + code |= *output++; + (*size)++; + } + return mpeg3bits_eof(vstream); +} + +int mpeg3video_read_frame(mpeg3video_t *video, + long frame_number, + unsigned char **output_rows, + int in_x, + int in_y, + int in_w, + int in_h, + int out_w, + int out_h, + int color_model) +{ + int result = 0; + + video->want_yvu = 0; + video->output_rows = output_rows; + video->color_model = color_model; + +/* Get scaling tables */ + if(video->out_w != out_w || video->out_h != out_h || + video->in_w != in_w || video->in_h != in_h || + video->in_x != in_x || video->in_y != in_y) + { + if(video->x_table) + { + free(video->x_table); + free(video->y_table); + video->x_table = 0; + video->y_table = 0; + } + } + + video->out_w = out_w; + video->out_h = out_h; + video->in_w = in_w; + video->in_h = in_h; + video->in_x = in_x; + video->in_y = in_y; + + if(!video->x_table) + { + video->x_table = mpeg3video_get_scaletable(video->in_w, video->out_w); + video->y_table = mpeg3video_get_scaletable(video->in_h, video->out_h); + } + + mpeg3video_get_firstframe(video); + + if(!result) result = mpeg3video_seek(video); + + if(!result) result = mpeg3video_read_frame_backend(video, 0); + + if(video->output_src) mpeg3video_present_frame(video); + + video->percentage_seek = -1; + return result; +} + +int mpeg3video_read_yuvframe(mpeg3video_t *video, + long frame_number, + char *y_output, + char *u_output, + char *v_output, + int in_x, + int in_y, + int in_w, + int in_h) +{ + int result = 0; + + video->want_yvu = 1; + video->y_output = y_output; + video->u_output = u_output; + video->v_output = v_output; + video->in_x = in_x; + video->in_y = in_y; + video->in_w = in_w; + video->in_h = in_h; + + mpeg3video_get_firstframe(video); + + if(!result) result = mpeg3video_seek(video); + + if(!result) result = mpeg3video_read_frame_backend(video, 0); + + if(video->output_src) mpeg3video_present_frame(video); + + video->want_yvu = 0; + video->percentage_seek = -1; + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.h b/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.h new file mode 100644 index 0000000..2db62b0 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.h @@ -0,0 +1,180 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEGVIDEO_H +#define MPEGVIDEO_H + +#include "../bitstream.h" +#include "../mpeg3private.inc" +#include "idct.h" +#include "slice.h" +#include "../timecode.h" + +/* zig-zag scan */ +extern unsigned char mpeg3_zig_zag_scan_nommx[64]; +extern unsigned char mpeg3_zig_zag_scan_mmx[64]; + +/* alternate scan */ +extern unsigned char mpeg3_alternate_scan_nommx[64]; +extern unsigned char mpeg3_alternate_scan_mmx[64]; + +/* default intra quantization matrix */ +extern unsigned char mpeg3_default_intra_quantizer_matrix[64]; + +/* Frame rate table must agree with the one in the encoder */ +extern double mpeg3_frame_rate_table[16]; + +/* non-linear quantization coefficient table */ +extern unsigned char mpeg3_non_linear_mquant_table[32]; + +#define CHROMA420 1 /* chroma_format */ +#define CHROMA422 2 +#define CHROMA444 3 + +#define TOP_FIELD 1 /* picture structure */ +#define BOTTOM_FIELD 2 +#define FRAME_PICTURE 3 + +#define SEQ_ID 1 /* extension start code IDs */ +#define DISP_ID 2 +#define QUANT_ID 3 +#define SEQSCAL_ID 5 +#define PANSCAN_ID 7 +#define CODING_ID 8 +#define SPATSCAL_ID 9 +#define TEMPSCAL_ID 10 + +#define ERROR (-1) + +#define SC_NONE 0 /* scalable_mode */ +#define SC_DP 1 +#define SC_SPAT 2 +#define SC_SNR 3 +#define SC_TEMP 4 + +#define I_TYPE 1 /* picture coding type */ +#define P_TYPE 2 +#define B_TYPE 3 +#define D_TYPE 4 + +#define MB_INTRA 1 /* macroblock type */ +#define MB_PATTERN 2 +#define MB_BACKWARD 4 +#define MB_FORWARD 8 +#define MB_QUANT 16 +#define MB_WEIGHT 32 +#define MB_CLASS4 64 + +#define MC_FIELD 1 /* motion_type */ +#define MC_FRAME 2 +#define MC_16X8 2 +#define MC_DMV 3 + +#define MV_FIELD 0 /* mv_format */ +#define MV_FRAME 1 + +#define CLIP(x) ((x) >= 0 ? ((x) < 255 ? (x) : 255) : 0) + +/* Statically allocate as little as possible so a fake video struct */ +/* can be used for reading the GOP headers. */ + +struct mpeg3video_rec +{ + struct mpeg3_rec* file; + struct mpeg3_vtrack_rec* track; + +/* ================================= Seeking variables ========================= */ + mpeg3_bits_t *vstream; + int decoder_initted; + unsigned char **output_rows; /* Output frame buffer supplied by user */ + int in_x, in_y, in_w, in_h, out_w, out_h; /* Output dimensions */ + int *x_table, *y_table; /* Location of every output pixel in the input */ + int color_model; + int want_yvu; /* Want to return a YUV frame */ + char *y_output, *u_output, *v_output; /* Output pointers for a YUV frame */ + + mpeg3_slice_t slice_decoders[MPEG3_MAX_CPUS]; /* One slice decoder for every CPU */ + int total_slice_decoders; /* Total slice decoders in use */ + mpeg3_slice_buffer_t slice_buffers[MPEG3_MAX_CPUS]; /* Buffers for holding the slice data */ + int total_slice_buffers; /* Total buffers in the array to be decompressed */ + int slice_buffers_initialized; /* Total buffers initialized in the array */ + pthread_mutex_t slice_lock; /* Lock slice array while getting the next buffer */ + pthread_mutex_t test_lock; + + int blockreadsize; + long maxframe; /* Max value of frame num to read */ + double percentage_seek; /* Perform a percentage seek before the next frame is read */ + int frame_seek; /* Perform a frame seek before the next frame is read */ + long framenum; /* Number of the next frame to be decoded */ + long last_number; /* Last framenum rendered */ + int found_seqhdr; + long bitrate; + mpeg3_timecode_t gop_timecode; /* Timecode for the last GOP header read. */ + +/* These are only available from elementary streams. */ + long frames_per_gop; /* Frames per GOP after the first GOP. */ + long first_gop_frames; /* Frames in the first GOP. */ + long first_frame; /* Number of first frame stored in timecode */ + long last_frame; /* Last frame in file */ + +/* ================================= Compression variables ===================== */ +/* Malloced frame buffers. 2 refframes are swapped in and out. */ +/* while only 1 auxframe is used. */ + unsigned char *yuv_buffer[5]; /* Make YVU buffers contiguous for all frames */ + unsigned char *oldrefframe[3], *refframe[3], *auxframe[3]; + unsigned char *llframe0[3], *llframe1[3]; + unsigned char *mpeg3_zigzag_scan_table; + unsigned char *mpeg3_alternate_scan_table; +// Source for the next frame presentation + unsigned char **output_src; +/* Pointers to frame buffers. */ + unsigned char *newframe[3]; + int horizontal_size, vertical_size, mb_width, mb_height; + int coded_picture_width, coded_picture_height; + int chroma_format, chrom_width, chrom_height, blk_cnt; + int pict_type; + int forw_r_size, back_r_size, full_forw, full_back; + int prog_seq, prog_frame; + int h_forw_r_size, v_forw_r_size, h_back_r_size, v_back_r_size; + int dc_prec, pict_struct, topfirst, frame_pred_dct, conceal_mv; + int intravlc; + int repeatfirst; + int repeat_count; /* Number of times to repeat the current frame * 100 since floating point is impossible in MMX */ + int current_repeat; /* Number of times the current frame has been repeated * 100 */ + int secondfield; + int skip_bframes; + int stwc_table_index, llw, llh, hm, hn, vm, vn; + int lltempref, llx0, lly0, llprog_frame, llfieldsel; + int matrix_coefficients; + int framerate_code; + float frame_rate; + long *cr_to_r, *cr_to_g, *cb_to_g, *cb_to_b; + long *cr_to_r_ptr, *cr_to_g_ptr, *cb_to_g_ptr, *cb_to_b_ptr; + int have_mmx; + int intra_quantizer_matrix[64], non_intra_quantizer_matrix[64]; + int chroma_intra_quantizer_matrix[64], chroma_non_intra_quantizer_matrix[64]; + int mpeg2; + int qscale_type, altscan; /* picture coding extension */ + int pict_scal; /* picture spatial scalable extension */ + int scalable_mode; /* sequence scalable extension */ +}; + +typedef struct mpeg3video_rec mpeg3video_t; + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/mpeg3videoprotos.h b/core/multimedia/opieplayer/libmpeg3/video/mpeg3videoprotos.h new file mode 100644 index 0000000..e48d6cd --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/mpeg3videoprotos.h @@ -0,0 +1,26 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3VIDEOPROTOS_H +#define MPEG3VIDEOPROTOS_H + +void mpeg3video_idct_conversion(short* block); +unsigned int mpeg3slice_showbits(mpeg3_slice_buffer_t *slice_buffer, int bits); + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/output.c b/core/multimedia/opieplayer/libmpeg3/video/output.c new file mode 100644 index 0000000..919a0ff --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/output.c @@ -0,0 +1,993 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include + +static LONGLONG mpeg3_MMX_0 = 0L; +static unsigned long mpeg3_MMX_10w[] = {0x00100010, 0x00100010}; /*dd 00010 0010h, 000100010h */ +static unsigned long mpeg3_MMX_80w[] = {0x00800080, 0x00800080}; /*dd 00080 0080h, 000800080h */ + +static unsigned long mpeg3_MMX_00FFw[] = {0x00ff00ff, 0x00ff00ff}; /*dd 000FF 00FFh, 000FF00FFh */ + +static unsigned short mpeg3_MMX_Ublucoeff[] = {0x81, 0x81, 0x81, 0x81}; /*dd 00081 0081h, 000810081h */ +static unsigned short mpeg3_MMX_Vredcoeff[] = {0x66, 0x66, 0x66, 0x66}; /*dd 00066 0066h, 000660066h */ + +static unsigned short mpeg3_MMX_Ugrncoeff[] = {0xffe8, 0xffe8, 0xffe8, 0xffe8}; /*dd 0FFE7 FFE7h, 0FFE7FFE7h */ +static unsigned short mpeg3_MMX_Vgrncoeff[] = {0xffcd, 0xffcd, 0xffcd, 0xffcd}; /*dd 0FFCC FFCCh, 0FFCCFFCCh */ + +static unsigned short mpeg3_MMX_Ycoeff[] = {0x4a, 0x4a, 0x4a, 0x4a}; /*dd 0004A 004Ah, 0004A004Ah */ + +static unsigned short mpeg3_MMX_redmask[] = {0xf800, 0xf800, 0xf800, 0xf800}; /*dd 07c00 7c00h, 07c007c00h */ + +static unsigned short mpeg3_MMX_grnmask[] = {0x7e0, 0x7e0, 0x7e0, 0x7e0}; /*dd 003e0 03e0h, 003e003e0h */ + +static unsigned char mpeg3_601_to_rgb[256]; + +/* Algorithm */ +/* r = (int)(*y + 1.371 * (*cr - 128)); */ +/* g = (int)(*y - 0.698 * (*cr - 128) - 0.336 * (*cb - 128)); */ +/* b = (int)(*y + 1.732 * (*cb - 128)); */ + +#ifdef HAVE_MMX +inline void mpeg3video_rgb16_mmx(unsigned char *lum, + unsigned char *cr, + unsigned char *cb, + unsigned char *out, + int rows, + int cols, + int mod) +{ + unsigned short *row1; + int x; + unsigned char *y; + int col1; + + row1 = (unsigned short *)out; + col1 = cols + mod; + mod += cols + mod; + mod *= 2; + y = lum + cols * rows; + x = 0; + + __asm__ __volatile__( + ".align 8\n" + "1:\n" + "movd (%1), %%mm0\n" /* 4 Cb 0 0 0 0 u3 u2 u1 u0 */ + "pxor %%mm7, %%mm7\n" + "movd (%0), %%mm1\n" /* 4 Cr 0 0 0 0 v3 v2 v1 v0 */ + "punpcklbw %%mm7, %%mm0\n" /* 4 W cb 0 u3 0 u2 0 u1 0 u0 */ + "punpcklbw %%mm7, %%mm1\n" /* 4 W cr 0 v3 0 v2 0 v1 0 v0 */ + + "psubw mpeg3_MMX_80w, %%mm0\n" + "psubw mpeg3_MMX_80w, %%mm1\n" + "movq %%mm0, %%mm2\n" /* Cb 0 u3 0 u2 0 u1 0 u0 */ + "movq %%mm1, %%mm3\n" /* Cr */ + "pmullw mpeg3_MMX_Ugrncoeff, %%mm2\n" /* Cb2green 0 R3 0 R2 0 R1 0 R0 */ + "movq (%2), %%mm6\n" /* L1 l7 L6 L5 L4 L3 L2 L1 L0 */ + "pmullw mpeg3_MMX_Ublucoeff, %%mm0\n" /* Cb2blue */ + "pand mpeg3_MMX_00FFw, %%mm6\n" /* L1 00 L6 00 L4 00 L2 00 L0 */ + "pmullw mpeg3_MMX_Vgrncoeff, %%mm3\n" /* Cr2green */ + "movq (%2), %%mm7\n" /* L2 */ + "pmullw mpeg3_MMX_Vredcoeff, %%mm1\n" /* Cr2red */ + "psrlw $8, %%mm7\n" /* L2 00 L7 00 L5 00 L3 00 L1 */ + "pmullw mpeg3_MMX_Ycoeff, %%mm6\n" /* lum1 */ + "paddw %%mm3, %%mm2\n" /* Cb2green + Cr2green == green */ + "pmullw mpeg3_MMX_Ycoeff, %%mm7\n" /* lum2 */ + + "movq %%mm6, %%mm4\n" /* lum1 */ + "paddw %%mm0, %%mm6\n" /* lum1 +blue 00 B6 00 B4 00 B2 00 B0 */ + "movq %%mm4, %%mm5\n" /* lum1 */ + "paddw %%mm1, %%mm4\n" /* lum1 +red 00 R6 00 R4 00 R2 00 R0 */ + "paddw %%mm2, %%mm5\n" /* lum1 +green 00 G6 00 G4 00 G2 00 G0 */ + "psraw $6, %%mm4\n" /* R1 0 .. 64 */ + "movq %%mm7, %%mm3\n" /* lum2 00 L7 00 L5 00 L3 00 L1 */ + "psraw $6, %%mm5\n" /* G1 - .. + */ + "paddw %%mm0, %%mm7\n" /* Lum2 +blue 00 B7 00 B5 00 B3 00 B1 */ + "psraw $6, %%mm6\n" /* B1 0 .. 64 */ + "packuswb %%mm4, %%mm4\n" /* R1 R1 */ + "packuswb %%mm5, %%mm5\n" /* G1 G1 */ + "packuswb %%mm6, %%mm6\n" /* B1 B1 */ + "punpcklbw %%mm4, %%mm4\n" + "punpcklbw %%mm5, %%mm5\n" + + "pand mpeg3_MMX_redmask, %%mm4\n" + "psllw $3, %%mm5\n" /* GREEN 1 */ + "punpcklbw %%mm6, %%mm6\n" + "pand mpeg3_MMX_grnmask, %%mm5\n" + "pand mpeg3_MMX_redmask, %%mm6\n" + "por %%mm5, %%mm4\n" /* */ + "psrlw $11, %%mm6\n" /* BLUE 1 */ + "movq %%mm3, %%mm5\n" /* lum2 */ + "paddw %%mm1, %%mm3\n" /* lum2 +red 00 R7 00 R5 00 R3 00 R1 */ + "paddw %%mm2, %%mm5\n" /* lum2 +green 00 G7 00 G5 00 G3 00 G1 */ + "psraw $6, %%mm3\n" /* R2 */ + "por %%mm6, %%mm4\n" /* MM4 */ + "psraw $6, %%mm5\n" /* G2 */ + "movq (%2, %3), %%mm6\n" /* L3 */ + "psraw $6, %%mm7\n" + "packuswb %%mm3, %%mm3\n" + "packuswb %%mm5, %%mm5\n" + "packuswb %%mm7, %%mm7\n" + "pand mpeg3_MMX_00FFw, %%mm6\n" /* L3 */ + "punpcklbw %%mm3, %%mm3\n" + "punpcklbw %%mm5, %%mm5\n" + "pmullw mpeg3_MMX_Ycoeff, %%mm6\n" /* lum3 */ + "punpcklbw %%mm7, %%mm7\n" + "psllw $3, %%mm5\n" /* GREEN 2 */ + "pand mpeg3_MMX_redmask, %%mm7\n" + "pand mpeg3_MMX_redmask, %%mm3\n" + "psrlw $11, %%mm7\n" /* BLUE 2 */ + "pand mpeg3_MMX_grnmask, %%mm5\n" + "por %%mm7, %%mm3\n" + "movq (%2,%3), %%mm7\n" /* L4 */ + "por %%mm5, %%mm3\n" /* */ + "psrlw $8, %%mm7\n" /* L4 */ + "movq %%mm4, %%mm5\n" + "punpcklwd %%mm3, %%mm4\n" + "pmullw mpeg3_MMX_Ycoeff, %%mm7\n" /* lum4 */ + "punpckhwd %%mm3, %%mm5\n" + + "movq %%mm4, (%4)\n" + "movq %%mm5, 8(%4)\n" + + "movq %%mm6, %%mm4\n" /* Lum3 */ + "paddw %%mm0, %%mm6\n" /* Lum3 +blue */ + + "movq %%mm4, %%mm5\n" /* Lum3 */ + "paddw %%mm1, %%mm4\n" /* Lum3 +red */ + "paddw %%mm2, %%mm5\n" /* Lum3 +green */ + "psraw $6, %%mm4\n" + "movq %%mm7, %%mm3\n" /* Lum4 */ + "psraw $6, %%mm5\n" + "paddw %%mm0, %%mm7\n" /* Lum4 +blue */ + "psraw $6, %%mm6\n" /* Lum3 +blue */ + "movq %%mm3, %%mm0\n" /* Lum4 */ + "packuswb %%mm4, %%mm4\n" + "paddw %%mm1, %%mm3\n" /* Lum4 +red */ + "packuswb %%mm5, %%mm5\n" + "paddw %%mm2, %%mm0\n" /* Lum4 +green */ + "packuswb %%mm6, %%mm6\n" + "punpcklbw %%mm4, %%mm4\n" + "punpcklbw %%mm5, %%mm5\n" + "punpcklbw %%mm6, %%mm6\n" + "psllw $3, %%mm5\n" /* GREEN 3 */ + "pand mpeg3_MMX_redmask, %%mm4\n" + "psraw $6, %%mm3\n" /* psr 6 */ + "psraw $6, %%mm0\n" + "pand mpeg3_MMX_redmask, %%mm6\n" /* BLUE */ + "pand mpeg3_MMX_grnmask, %%mm5\n" + "psrlw $11, %%mm6\n" /* BLUE 3 */ + "por %%mm5, %%mm4\n" + "psraw $6, %%mm7\n" + "por %%mm6, %%mm4\n" + "packuswb %%mm3, %%mm3\n" + "packuswb %%mm0, %%mm0\n" + "packuswb %%mm7, %%mm7\n" + "punpcklbw %%mm3, %%mm3\n" + "punpcklbw %%mm0, %%mm0\n" + "punpcklbw %%mm7, %%mm7\n" + "pand mpeg3_MMX_redmask, %%mm3\n" + "pand mpeg3_MMX_redmask, %%mm7\n" /* BLUE */ + "psllw $3, %%mm0\n" /* GREEN 4 */ + "psrlw $11, %%mm7\n" + "pand mpeg3_MMX_grnmask, %%mm0\n" + "por %%mm7, %%mm3\n" + "addl $8, %6\n" + "por %%mm0, %%mm3\n" + + "movq %%mm4, %%mm5\n" + + "punpcklwd %%mm3, %%mm4\n" + "punpckhwd %%mm3, %%mm5\n" + + "movq %%mm4, (%4,%5,2)\n" + "movq %%mm5, 8(%4,%5,2)\n" + + "addl $8, %2\n" + "addl $4, %0\n" + "addl $4, %1\n" + "cmpl %3, %6\n" + "leal 16(%4), %4\n" + "jl 1b\n" + "addl %3, %2\n" /* lum += cols */ + "addl %7, %4\n" /* row1 += mod */ + "movl $0, %6\n" + "cmpl %8, %2\n" + "jl 1b\n" + : : "r" (cr), + "r" (cb), + "r" (lum), + "r" (cols), + "r" (row1) , + "r" (col1), + "m" (x), + "m" (mod), + "m" (y) + ); +} + +static unsigned LONGLONG mpeg3_MMX_U_80 = 0x0000008000800000LL; +static unsigned LONGLONG mpeg3_MMX_V_80 = 0x0000000000800080LL; +static LONGLONG mpeg3_MMX_U_COEF = 0x00000058ffd30000LL; +static LONGLONG mpeg3_MMX_V_COEF = 0x00000000ffea006fLL; +static LONGLONG mpeg3_MMX_601_Y_COEF = 0x0000004800480048LL; +static LONGLONG mpeg3_MMX_601_Y_DIFF = 0x0000000000000010LL; + +inline void mpeg3_bgra32_mmx(unsigned long y, + unsigned long u, + unsigned long v, + unsigned long *output) +{ +asm(" +/* Output will be 0x00rrggbb with the 00 trailing so this can also be used */ +/* for bgr24. */ + movd (%0), %%mm0; /* Load y 0x00000000000000yy */ + movd (%1), %%mm1; /* Load u 0x00000000000000cr */ + movq %%mm0, %%mm3; /* Copy y to temp */ + psllq $16, %%mm1; /* Shift u 0x0000000000cr0000 */ + movd (%2), %%mm2; /* Load v 0x00000000000000cb */ + psllq $16, %%mm3; /* Shift y */ + movq %%mm1, %%mm4; /* Copy u to temp */ + por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */ + psllq $16, %%mm4; /* Shift u */ + movq %%mm2, %%mm5; /* Copy v to temp */ + psllq $16, %%mm3; /* Shift y */ + por %%mm4, %%mm1; /* Overlay new u byte 0x000000cr00cr0000 */ + psllq $16, %%mm5; /* Shift v */ + por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */ + por %%mm5, %%mm2; /* Overlay new v byte 0x0000000000cb00cb */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x000000uu00uu0000 mm2: 0x0000000000vv00vv */ + psubw mpeg3_MMX_U_80, %%mm1; /* Subtract 128 from u 0x000000uu00uu0000 */ + pmullw mpeg3_MMX_U_COEF, %%mm1; /* Multiply u coeffs 0x0000uuuuuuuu0000 */ + psllw $6, %%mm0; /* Shift y coeffs 0x0000yyy0yyy0yyy0 */ + psubw mpeg3_MMX_V_80, %%mm2; /* Subtract 128 from v 0x0000000000cb00cb */ + pmullw mpeg3_MMX_V_COEF, %%mm2; /* Multiply v coeffs 0x0000crcrcrcrcrcr */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x0000uuuuuuuu0000 mm2: 0x00000000vvvvvvvv */ + paddsw %%mm1, %%mm0; /* Add u to result */ + paddsw %%mm2, %%mm0; /* Add v to result 0x0000rrrrggggbbbb */ + psraw $6, %%mm0; /* Demote precision */ + packuswb %%mm0, %%mm0; /* Pack into ARGB 0x0000000000rrggbb */ + movd %%mm0, (%3); /* Store output */ + " +: +: "r" (&y), "r" (&u), "r" (&v), "r" (output)); +} + +inline void mpeg3_601_bgra32_mmx(unsigned long y, + unsigned long u, + unsigned long v, + unsigned long *output) +{ +asm(" +/* Output will be 0x00rrggbb with the 00 trailing so this can also be used */ +/* for bgr24. */ + movd (%0), %%mm0; /* Load y 0x00000000000000yy */ + psubsw mpeg3_MMX_601_Y_DIFF, %%mm0; /* Subtract 16 from y */ + movd (%1), %%mm1; /* Load u 0x00000000000000cr */ + movq %%mm0, %%mm3; /* Copy y to temp */ + psllq $16, %%mm1; /* Shift u 0x0000000000cr0000 */ + movd (%2), %%mm2; /* Load v 0x00000000000000cb */ + psllq $16, %%mm3; /* Shift y */ + movq %%mm1, %%mm4; /* Copy u to temp */ + por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */ + psllq $16, %%mm4; /* Shift u */ + movq %%mm2, %%mm5; /* Copy v to temp */ + psllq $16, %%mm3; /* Shift y */ + por %%mm4, %%mm1; /* Overlay new u byte 0x000000cr00cr0000 */ + psllq $16, %%mm5; /* Shift v */ + por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */ + por %%mm5, %%mm2; /* Overlay new v byte 0x0000000000cb00cb */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x000000uu00uu0000 mm2: 0x0000000000vv00vv */ + pmullw mpeg3_MMX_601_Y_COEF, %%mm0; /* Scale and shift y coeffs */ + psubw mpeg3_MMX_U_80, %%mm1; /* Subtract 128 from u 0x000000uu00uu0000 */ + pmullw mpeg3_MMX_U_COEF, %%mm1; /* Multiply u coeffs 0x0000uuuuuuuu0000 */ + psubw mpeg3_MMX_V_80, %%mm2; /* Subtract 128 from v 0x0000000000cb00cb */ + pmullw mpeg3_MMX_V_COEF, %%mm2; /* Multiply v coeffs 0x0000crcrcrcrcrcr */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x0000uuuuuuuu0000 mm2: 0x00000000vvvvvvvv */ + paddsw %%mm1, %%mm0; /* Add u to result */ + paddsw %%mm2, %%mm0; /* Add v to result 0x0000rrrrggggbbbb */ + psraw $6, %%mm0; /* Demote precision */ + packuswb %%mm0, %%mm0; /* Pack into ARGB 0x0000000000rrggbb */ + movd %%mm0, (%3); /* Store output */ + " +: +: "r" (&y), "r" (&u), "r" (&v), "r" (output)); +} + +static unsigned LONGLONG mpeg3_MMX_U_80_RGB = 0x0000000000800080LL; +static unsigned LONGLONG mpeg3_MMX_V_80_RGB = 0x0000008000800000LL; +static LONGLONG mpeg3_MMX_U_COEF_RGB = 0x00000000ffd30058LL; +static LONGLONG mpeg3_MMX_V_COEF_RGB = 0x0000006fffea0000LL; + +inline void mpeg3_rgba32_mmx(unsigned long y, + unsigned long u, + unsigned long v, + unsigned long *output) +{ +asm(" +/* Output will be 0x00bbggrr with the 00 trailing so this can also be used */ +/* for rgb24. */ + movd (%0), %%mm0; /* Load y 0x00000000000000yy */ + movd (%1), %%mm1; /* Load v 0x00000000000000vv */ + movq %%mm0, %%mm3; /* Copy y to temp */ + psllq $16, %%mm1; /* Shift v 0x0000000000vv0000 */ + movd (%2), %%mm2; /* Load u 0x00000000000000uu */ + psllq $16, %%mm3; /* Shift y */ + movq %%mm1, %%mm4; /* Copy v to temp */ + por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */ + psllq $16, %%mm4; /* Shift v */ + movq %%mm2, %%mm5; /* Copy u to temp */ + psllq $16, %%mm3; /* Shift y */ + por %%mm4, %%mm1; /* Overlay new v byte 0x000000vv00vv0000 */ + psllq $16, %%mm5; /* Shift u */ + por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */ + por %%mm5, %%mm2; /* Overlay new u byte 0x0000000000uu00uu */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x000000vv00vv0000 mm2: 0x0000000000uu00uu */ + psubw mpeg3_MMX_V_80_RGB, %%mm1; /* Subtract 128 from v 0x000000vv00vv0000 */ + pmullw mpeg3_MMX_V_COEF_RGB, %%mm1; /* Multiply v coeffs 0x0000vvvvvvvv0000 */ + psllw $6, %%mm0; /* Shift y coeffs 0x0000yyy0yyy0yyy0 */ + psubw mpeg3_MMX_U_80_RGB, %%mm2; /* Subtract 128 from u 0x0000000000uu00uu */ + pmullw mpeg3_MMX_U_COEF_RGB, %%mm2; /* Multiply u coeffs 0x0000uuuuuuuuuuuu */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x0000vvvvvvvv0000 mm2: 0x00000000uuuuuuuu */ + paddsw %%mm1, %%mm0; /* Add v to result */ + paddsw %%mm2, %%mm0; /* Add u to result 0x0000bbbbggggrrrr */ + psraw $6, %%mm0; /* Demote precision */ + packuswb %%mm0, %%mm0; /* Pack into RGBA 0x0000000000bbggrr */ + movd %%mm0, (%3); /* Store output */ + " +: +: "r" (&y), "r" (&v), "r" (&u), "r" (output)); +} + +inline void mpeg3_601_rgba32_mmx(unsigned long y, + unsigned long u, + unsigned long v, + unsigned long *output) +{ +asm(" +/* Output will be 0x00bbggrr with the 00 trailing so this can also be used */ +/* for rgb24. */ + movd (%0), %%mm0; /* Load y 0x00000000000000yy */ + psubsw mpeg3_MMX_601_Y_DIFF, %%mm0; /* Subtract 16 from y */ + movd (%1), %%mm1; /* Load v 0x00000000000000vv */ + movq %%mm0, %%mm3; /* Copy y to temp */ + psllq $16, %%mm1; /* Shift v 0x0000000000vv0000 */ + movd (%2), %%mm2; /* Load u 0x00000000000000uu */ + psllq $16, %%mm3; /* Shift y */ + movq %%mm1, %%mm4; /* Copy v to temp */ + por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */ + psllq $16, %%mm4; /* Shift v */ + movq %%mm2, %%mm5; /* Copy u to temp */ + psllq $16, %%mm3; /* Shift y */ + por %%mm4, %%mm1; /* Overlay new v byte 0x000000vv00vv0000 */ + psllq $16, %%mm5; /* Shift u */ + por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */ + por %%mm5, %%mm2; /* Overlay new u byte 0x0000000000uu00uu */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x000000vv00vv0000 mm2: 0x0000000000uu00uu */ + pmullw mpeg3_MMX_601_Y_COEF, %%mm0; /* Scale y coeffs */ + psubw mpeg3_MMX_V_80_RGB, %%mm1; /* Subtract 128 from v 0x000000vv00vv0000 */ + pmullw mpeg3_MMX_V_COEF_RGB, %%mm1; /* Multiply v coeffs 0x0000vvvvvvvv0000 */ + psubw mpeg3_MMX_U_80_RGB, %%mm2; /* Subtract 128 from u 0x0000000000uu00uu */ + pmullw mpeg3_MMX_U_COEF_RGB, %%mm2; /* Multiply u coeffs 0x0000uuuuuuuuuuuu */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x0000vvvvvvvv0000 mm2: 0x00000000uuuuuuuu */ + paddsw %%mm1, %%mm0; /* Add v to result */ + paddsw %%mm2, %%mm0; /* Add u to result 0x0000bbbbggggrrrr */ + psraw $6, %%mm0; /* Demote precision */ + packuswb %%mm0, %%mm0; /* Pack into RGBA 0x0000000000bbggrr */ + movd %%mm0, (%3); /* Store output */ + " +: +: "r" (&y), "r" (&v), "r" (&u), "r" (output)); +} + +#endif + +#define DITHER_ROW_HEAD \ + for(h = 0; h < video->out_h; h++) \ + { \ + y_in = &src[0][(video->y_table[h] + video->in_y) * video->coded_picture_width] + video->in_x; \ + cb_in = &src[1][((video->y_table[h] + video->in_y) >> 1) * video->chrom_width] + (video->in_x >> 2); \ + cr_in = &src[2][((video->y_table[h] + video->in_y) >> 1) * video->chrom_width] + (video->in_x >> 1); \ + data = output_rows[h]; + +#define DITHER_ROW_TAIL \ + } + +#define DITHER_SCALE_HEAD \ + for(w = 0; w < video->out_w; w++) \ + { \ + uv_subscript = video->x_table[w] / 2; \ + y_l = y_in[video->x_table[w]]; \ + y_l <<= 16; \ + r_l = (y_l + video->cr_to_r[cr_in[uv_subscript]]) >> 16; \ + g_l = (y_l + video->cr_to_g[cr_in[uv_subscript]] + video->cb_to_g[cb_in[uv_subscript]]) >> 16; \ + b_l = (y_l + video->cb_to_b[cb_in[uv_subscript]]) >> 16; + +#define DITHER_SCALE_601_HEAD \ + for(w = 0; w < video->out_w; w++) \ + { \ + uv_subscript = video->x_table[w] / 2; \ + y_l = mpeg3_601_to_rgb[y_in[video->x_table[w]]]; \ + y_l <<= 16; \ + r_l = (y_l + video->cr_to_r[cr_in[uv_subscript]]) >> 16; \ + g_l = (y_l + video->cr_to_g[cr_in[uv_subscript]] + video->cb_to_g[cb_in[uv_subscript]]) >> 16; \ + b_l = (y_l + video->cb_to_b[cb_in[uv_subscript]]) >> 16; + +#define DITHER_SCALE_TAIL \ + } + +#define DITHER_MMX_SCALE_HEAD \ + for(w = 0; w < video->out_w; w++) \ + { \ + uv_subscript = video->x_table[w] / 2; + +#define DITHER_MMX_SCALE_TAIL \ + data += step; \ + } + +#define DITHER_MMX_HEAD \ + for(w = 0; w < video->out_w; w += 2) \ + { + +#define DITHER_MMX_TAIL \ + data += step; \ + cr_in++; \ + cb_in++; \ + } + +#define DITHER_HEAD \ + for(w = 0; w < video->horizontal_size; w++) \ + { \ + y_l = *y_in++; \ + y_l <<= 16; \ + r_l = (y_l + video->cr_to_r[*cr_in]) >> 16; \ + g_l = (y_l + video->cr_to_g[*cr_in] + video->cb_to_g[*cb_in]) >> 16; \ + b_l = (y_l + video->cb_to_b[*cb_in]) >> 16; + +#define DITHER_601_HEAD \ + for(w = 0; w < video->horizontal_size; w++) \ + { \ + y_l = mpeg3_601_to_rgb[*y_in++]; \ + y_l <<= 16; \ + r_l = (y_l + video->cr_to_r[*cr_in]) >> 16; \ + g_l = (y_l + video->cr_to_g[*cr_in] + video->cb_to_g[*cb_in]) >> 16; \ + b_l = (y_l + video->cb_to_b[*cb_in]) >> 16; + +#define DITHER_TAIL \ + if(w & 1) \ + { \ + cr_in++; \ + cb_in++; \ + } \ + } + + +#define STORE_PIXEL_BGR888 \ + *data++ = CLIP(b_l); \ + *data++ = CLIP(g_l); \ + *data++ = CLIP(r_l); + +#define STORE_PIXEL_BGRA8888 \ + *data++ = CLIP(b_l); \ + *data++ = CLIP(g_l); \ + *data++ = CLIP(r_l); \ + *data++ = 0; + +#define STORE_PIXEL_RGB565 \ + *((unsigned short*)data)++ = \ + ((CLIP(r_l) & 0xf8) << 8) | \ + ((CLIP(g_l) & 0xfc) << 3) | \ + ((CLIP(b_l) & 0xf8) >> 3); + +#define STORE_PIXEL_RGB888 \ + *data++ = CLIP(r_l); \ + *data++ = CLIP(g_l); \ + *data++ = CLIP(b_l); + +#define STORE_PIXEL_RGBA8888 \ + *data++ = CLIP(r_l); \ + *data++ = CLIP(g_l); \ + *data++ = CLIP(b_l); \ + *data++ = 0; + +#define STORE_PIXEL_RGBA16161616 \ + *data_s++ = CLIP(r_l); \ + *data_s++ = CLIP(g_l); \ + *data_s++ = CLIP(b_l); \ + *data_s++ = 0; + + + +/* Only good for YUV 4:2:0 */ +int mpeg3video_ditherframe(mpeg3video_t *video, unsigned char **src, unsigned char **output_rows) +{ + int h = 0; + register unsigned char *y_in, *cb_in, *cr_in; + long y_l, r_l, b_l, g_l; + register unsigned char *data; + register int uv_subscript, step, w = -1; + +#ifdef HAVE_MMX +/* =================================== MMX ===================================== */ + if(video->have_mmx && + video->out_w == video->horizontal_size && + video->out_h == video->vertical_size && + video->in_w == video->out_w && + video->in_h == video->out_h && + video->in_x == 0 && + video->in_y == 0 && + (video->color_model == MPEG3_RGB565 || video->color_model == MPEG3_601_RGB565)) + { +/* Unscaled 16 bit */ + mpeg3video_rgb16_mmx(src[0], + src[2], + src[1], + output_rows[0], + video->out_h, + video->out_w, + (output_rows[1] - output_rows[0]) / 2 - video->out_w); + } + else + if(video->have_mmx && + (video->color_model == MPEG3_BGRA8888 || + video->color_model == MPEG3_BGR888 || +/* video->color_model == MPEG3_RGB888 || */ + video->color_model == MPEG3_RGBA8888 || + video->color_model == MPEG3_601_BGR888 || + video->color_model == MPEG3_601_BGRA8888 || + video->color_model == MPEG3_601_RGB888 || + video->color_model == MPEG3_601_RGBA8888)) + { +/* Original MMX */ + if(video->color_model == MPEG3_BGRA8888 || + video->color_model == MPEG3_RGBA8888 || + video->color_model == MPEG3_601_BGRA8888 || + video->color_model == MPEG3_601_RGBA8888) step = 4; + else + if(video->color_model == MPEG3_BGR888 || + video->color_model == MPEG3_RGB888 || + video->color_model == MPEG3_601_BGR888 || + video->color_model == MPEG3_601_RGB888) step = 3; + + DITHER_ROW_HEAD +/* Transfer row with scaling */ + if(video->out_w != video->horizontal_size) + { + switch(video->color_model) + { + case MPEG3_BGRA8888: + case MPEG3_BGR888: + DITHER_MMX_SCALE_HEAD + mpeg3_bgra32_mmx(y_in[video->x_table[w]], + cr_in[uv_subscript], + cb_in[uv_subscript], + (unsigned long*)data); + DITHER_MMX_SCALE_TAIL + break; + + case MPEG3_601_BGRA8888: + case MPEG3_601_BGR888: + DITHER_MMX_SCALE_HEAD + mpeg3_601_bgra32_mmx(y_in[video->x_table[w]], + cr_in[uv_subscript], + cb_in[uv_subscript], + (unsigned long*)data); + DITHER_MMX_SCALE_TAIL + break; + + case MPEG3_RGBA8888: + case MPEG3_RGB888: + DITHER_MMX_SCALE_HEAD + mpeg3_rgba32_mmx(y_in[video->x_table[w]], + cr_in[uv_subscript], + cb_in[uv_subscript], + (unsigned long*)data); + DITHER_MMX_SCALE_TAIL + break; + + case MPEG3_601_RGBA8888: + case MPEG3_601_RGB888: + DITHER_MMX_SCALE_HEAD + mpeg3_601_rgba32_mmx(y_in[video->x_table[w]], + cr_in[uv_subscript], + cb_in[uv_subscript], + (unsigned long*)data); + DITHER_MMX_SCALE_TAIL + break; + } + } + else +/* Transfer row unscaled */ + { + switch(video->color_model) + { +/* MMX byte swap 24 and 32 bit */ + case MPEG3_BGRA8888: + case MPEG3_BGR888: + DITHER_MMX_HEAD + mpeg3_bgra32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + data += step; + mpeg3_bgra32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + DITHER_MMX_TAIL + break; + +/* MMX 601 byte swap 24 and 32 bit */ + case MPEG3_601_BGRA8888: + case MPEG3_601_BGR888: + DITHER_MMX_HEAD + mpeg3_601_bgra32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + data += step; + mpeg3_601_bgra32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + DITHER_MMX_TAIL + break; + +/* MMX 24 and 32 bit no byte swap */ + case MPEG3_RGBA8888: + case MPEG3_RGB888: + DITHER_MMX_HEAD + mpeg3_rgba32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + data += step; + mpeg3_rgba32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + DITHER_MMX_TAIL + break; + +/* MMX 601 24 and 32 bit no byte swap */ + case MPEG3_601_RGBA8888: + case MPEG3_601_RGB888: + DITHER_MMX_HEAD + mpeg3_601_rgba32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + data += step; + mpeg3_601_rgba32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + DITHER_MMX_TAIL + break; + } + } + DITHER_ROW_TAIL + } + else +#endif +/* ================================== NO MMX ==================================== */ + { + DITHER_ROW_HEAD +/* Transfer row with scaling */ + if(video->out_w != video->horizontal_size) + { + switch(video->color_model) + { + case MPEG3_BGR888: + DITHER_SCALE_HEAD + STORE_PIXEL_BGR888 + DITHER_SCALE_TAIL + break; + case MPEG3_BGRA8888: + DITHER_SCALE_HEAD + STORE_PIXEL_BGRA8888 + DITHER_SCALE_TAIL + break; + case MPEG3_RGB565: + DITHER_SCALE_HEAD + STORE_PIXEL_RGB565 + DITHER_SCALE_TAIL + break; + case MPEG3_RGB888: + DITHER_SCALE_HEAD + STORE_PIXEL_RGB888 + DITHER_SCALE_TAIL + break; + case MPEG3_RGBA8888: + DITHER_SCALE_HEAD + STORE_PIXEL_RGBA8888 + DITHER_SCALE_TAIL + break; + case MPEG3_601_BGR888: + DITHER_SCALE_601_HEAD + STORE_PIXEL_BGR888 + DITHER_SCALE_TAIL + break; + case MPEG3_601_BGRA8888: + DITHER_SCALE_601_HEAD + STORE_PIXEL_BGRA8888 + DITHER_SCALE_TAIL + break; + case MPEG3_601_RGB565: + DITHER_SCALE_601_HEAD + STORE_PIXEL_RGB565 + DITHER_SCALE_TAIL + break; + case MPEG3_601_RGB888: + DITHER_SCALE_601_HEAD + STORE_PIXEL_RGB888 + DITHER_SCALE_TAIL + break; + case MPEG3_601_RGBA8888: + DITHER_SCALE_601_HEAD + STORE_PIXEL_RGBA8888 + DITHER_SCALE_TAIL + break; + case MPEG3_RGBA16161616: + { + register unsigned short *data_s = (unsigned short*)data; + DITHER_SCALE_HEAD + STORE_PIXEL_RGBA16161616 + DITHER_SCALE_TAIL + } + break; + } + } + else + { +/* Transfer row unscaled */ + switch(video->color_model) + { + case MPEG3_BGR888: + DITHER_HEAD + STORE_PIXEL_BGR888 + DITHER_TAIL + break; + case MPEG3_BGRA8888: + DITHER_HEAD + STORE_PIXEL_BGRA8888 + DITHER_TAIL + break; + case MPEG3_RGB565: + DITHER_HEAD + STORE_PIXEL_RGB565 + DITHER_TAIL + break; + case MPEG3_RGB888: + DITHER_HEAD + STORE_PIXEL_RGB888 + DITHER_TAIL + break; + case MPEG3_RGBA8888: + DITHER_HEAD + STORE_PIXEL_RGBA8888 + DITHER_TAIL + break; + case MPEG3_601_BGR888: + DITHER_601_HEAD + STORE_PIXEL_BGR888 + DITHER_TAIL + break; + case MPEG3_601_BGRA8888: + DITHER_601_HEAD + STORE_PIXEL_RGB565 + DITHER_TAIL + break; + case MPEG3_601_RGB565: + DITHER_601_HEAD + STORE_PIXEL_RGB565 + DITHER_TAIL + break; + case MPEG3_601_RGB888: + DITHER_601_HEAD + STORE_PIXEL_RGB888 + DITHER_TAIL + break; + case MPEG3_601_RGBA8888: + DITHER_601_HEAD + STORE_PIXEL_RGBA8888 + DITHER_TAIL + break; + case MPEG3_RGBA16161616: + { + register unsigned short *data_s = (unsigned short*)data; + DITHER_HEAD + STORE_PIXEL_RGBA16161616 + DITHER_TAIL + } + break; + } + } + DITHER_ROW_TAIL + } /* End of non-MMX */ + +#ifdef HAVE_MMX + if(video->have_mmx) + __asm__ __volatile__ ("emms"); +#endif + return 0; +} + +int mpeg3video_ditherframe444(mpeg3video_t *video, unsigned char *src[]) +{ + return 0; +} + +int mpeg3video_dithertop(mpeg3video_t *video, unsigned char *src[]) +{ + return mpeg3video_ditherframe(video, src, video->output_rows); +} + +int mpeg3video_dithertop444(mpeg3video_t *video, unsigned char *src[]) +{ + return 0; +} + +int mpeg3video_ditherbot(mpeg3video_t *video, unsigned char *src[]) +{ + return 0; +} + +int mpeg3video_ditherbot444(mpeg3video_t *video, unsigned char *src[]) +{ + return 0; +} + +void memcpy_fast(unsigned char *output, unsigned char *input, long len) +{ + int i, len2; +/* 8 byte alignment */ +/* + * if(!((long)input & 0x7)) + * { + * len2 = len >> 4; + * for(i = 0; i < len2; ) + * { + * ((MPEG3_INT64*)output)[i] = ((MPEG3_INT64*)input)[i]; + * i++; + * ((MPEG3_INT64*)output)[i] = ((MPEG3_INT64*)input)[i]; + * i++; + * } + * + * for(i *= 16; i < len; i++) + * { + * output[i] = input[i]; + * } + * } + * else + */ + memcpy(output, input, len); +} + +int mpeg3video_init_output() +{ + int i, value; + for(i = 0; i < 256; i++) + { + value = (int)(1.1644 * i - 255 * 0.0627 + 0.5); + if(value < 0) value = 0; + else + if(value > 255) value = 255; + mpeg3_601_to_rgb[i] = value; + } + return 0; +} + +int mpeg3video_present_frame(mpeg3video_t *video) +{ + int i, j, k, l; + unsigned char **src = video->output_src; + +/* Copy YUV buffers */ + if(video->want_yvu) + { + long size[2]; + long offset[2]; + +/* Drop a frame */ + if(!video->y_output) return 0; + +/* Copy a frame */ + if(video->in_x == 0 && + video->in_w >= video->coded_picture_width) + { + size[0] = video->coded_picture_width * video->in_h; + size[1] = video->chrom_width * (int)((float)video->in_h / 2 + 0.5); + offset[0] = video->coded_picture_width * video->in_y; + offset[1] = video->chrom_width * (int)((float)video->in_y / 2 + 0.5); + +/* + * if(video->in_y > 0) + * { + * offset[1] += video->chrom_width / 2; + * size[1] += video->chrom_width / 2; + * } + */ + + memcpy(video->y_output, src[0] + offset[0], size[0]); + memcpy(video->u_output, src[1] + offset[1], size[1]); + memcpy(video->v_output, src[2] + offset[1], size[1]); + } + else + { + for(i = 0, j = video->in_y; i < video->in_h; i++, j++) + { + memcpy(video->y_output + i * video->in_w, + src[0] + j * video->coded_picture_width + video->in_x, + video->in_w); + memcpy(video->u_output + i * video->in_w / 4, + src[1] + j * video->chrom_width / 2 + video->in_x / 4, + video->in_w / 4); + memcpy(video->v_output + i * video->in_w / 4, + src[2] + j * video->chrom_width / 2 + video->in_x / 4, + video->in_w / 4); + } + } + + return 0; + } + +/* Want RGB buffer */ +/* Copy the frame to the output with YUV to RGB conversion */ + if(video->prog_seq) + { + if(video->chroma_format != CHROMA444) + { + mpeg3video_ditherframe(video, src, video->output_rows); + } + else + mpeg3video_ditherframe444(video, src); + } + else + { + if((video->pict_struct == FRAME_PICTURE && video->topfirst) || + video->pict_struct == BOTTOM_FIELD) + { +/* top field first */ + if(video->chroma_format != CHROMA444) + { + mpeg3video_dithertop(video, src); + mpeg3video_ditherbot(video, src); + } + else + { + mpeg3video_dithertop444(video, src); + mpeg3video_ditherbot444(video, src); + } + } + else + { +/* bottom field first */ + if(video->chroma_format != CHROMA444) + { + mpeg3video_ditherbot(video, src); + mpeg3video_dithertop(video, src); + } + else + { + mpeg3video_ditherbot444(video, src); + mpeg3video_dithertop444(video, src); + } + } + } + return 0; +} + +int mpeg3video_display_second_field(mpeg3video_t *video) +{ +/* Not used */ + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/reconmmx.s b/core/multimedia/opieplayer/libmpeg3/video/reconmmx.s new file mode 100644 index 0000000..1bb98ef --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/reconmmx.s @@ -0,0 +1,301 @@ +ADD_1: dd 01010101h, 01010101h +MASK_AND: dd 7f7f7f7fh, 7f7f7f7fh +PLUS_384: dd 01800180h, 01800180h +PLUS_128: dd 00800080h, 00800080h + +%assign LocalFrameSize 0 +%assign RegisterStorageSize 16 + +; Arguments: +%assign source LocalFrameSize + RegisterStorageSize + 4 +%assign dest LocalFrameSize + RegisterStorageSize + 8 +%assign lx2 LocalFrameSize + RegisterStorageSize + 12 +%assign h LocalFrameSize + RegisterStorageSize + 16 + +; Locals (on local stack frame) + + +; extern void C rec_mmx ( +; unsigned char *source, +; unsigned char *dest, +; int lx2, +; int h +; +; The local variables are on the stack, +; + +global recva_mmx +global recvac_mmx +global rech_mmx +global rechc_mmx +global add_block_mmx +global set_block_mmx + + + align 16 +rech_mmx: + push esi + push edi + push ecx + push ebx + mov esi, [esp+source] + mov edi, [esp+dest] + mov ecx, [esp+h] + mov ebx, [esp+lx2] + movq mm5, [MASK_AND] + movq mm6, [ADD_1] +.rech1: + movq mm0,[esi] + movq mm1,[esi+1] + movq mm2,[esi+8] + movq mm3,[esi+9] + psrlw mm0,1 + psrlw mm1,1 + psrlw mm2,1 + psrlw mm3,1 + pand mm0,mm5 + pand mm1,mm5 + pand mm2,mm5 + pand mm3,mm5 + paddusb mm0,mm1 + paddusb mm2,mm3 + paddusb mm0,mm6 + paddusb mm2,mm6 + movq [edi],mm0 + add esi,ebx + movq [edi+8],mm2 + add edi,ebx + dec ecx + jnz .rech1 + emms + pop ebx + pop ecx + pop edi + pop esi + ret + + align 16 +rechc_mmx: + push esi + push edi + push ecx + push ebx +; sub esp, LocalFrameSize + mov esi, [esp+source] + mov edi, [esp+dest] + mov ecx, [esp+h] + mov ebx, [esp+lx2] + movq mm5, [MASK_AND] + movq mm6, [ADD_1] +.rechc1: + movq mm0,[esi] + movq mm1,[esi+1] + psrlw mm0,1 + psrlw mm1,1 + pand mm0,mm5 + pand mm1,mm5 + paddusb mm0,mm1 + paddusb mm0,mm6 + movq [edi],mm0 + add edi,ebx + add esi,ebx + dec ecx + jnz .rechc1 + emms +; add esp, LocalFrameSize + pop ebx + pop ecx + pop edi + pop esi + ret + + + +%assign RegisterStorageSize 20 +%assign source LocalFrameSize + RegisterStorageSize + 4 +%assign dest LocalFrameSize + RegisterStorageSize + 8 +%assign lx LocalFrameSize + RegisterStorageSize + 12 +%assign lx2 LocalFrameSize + RegisterStorageSize + 16 +%assign h LocalFrameSize + RegisterStorageSize + 20 + + align 16 +recva_mmx: + push esi + push edi + push ecx + push ebx + push edx + mov esi, [esp+source] + mov edi, [esp+dest] + mov ecx, [esp+h] + mov ebx, [esp+lx2] + mov edx, [esp+lx] + movq mm7, [MASK_AND] + movq mm6, [ADD_1] +.recva1: + movq mm0,[esi] + movq mm1,[esi+edx] + movq mm2,[esi+8] + movq mm3,[esi+edx+8] + movq mm4,[edi] + movq mm5,[edi+8] + psrlw mm0,1 + psrlw mm1,1 + psrlw mm2,1 + psrlw mm3,1 + psrlw mm4,1 + psrlw mm5,1 + pand mm0,mm7 + pand mm1,mm7 + pand mm2,mm7 + pand mm3,mm7 + pand mm4,mm7 + pand mm5,mm7 + paddusb mm0,mm1 + paddusb mm2,mm3 + paddusb mm0,mm6 + paddusb mm2,mm6 + psrlw mm0,1 + psrlw mm2,1 + pand mm0,mm7 + pand mm2,mm7 + paddusb mm4,mm0 + paddusb mm5,mm2 + paddusb mm4,mm6 + paddusb mm5,mm6 + movq [edi],mm4 + movq [edi+8],mm5 + add edi,ebx + add esi,ebx + dec ecx + jnz near .recva1 + emms + pop edx + pop ebx + pop ecx + pop edi + pop esi + ret + + align 16 +recvac_mmx: + push esi + push edi + push ecx + push ebx + push edx + mov esi, [esp+source] + mov edi, [esp+dest] + mov ecx, [esp+h] + mov ebx, [esp+lx2] + mov edx, [esp+lx] + movq mm5, [MASK_AND] + movq mm6, [ADD_1] +.recvac1: + movq mm0,[esi] + movq mm1,[esi+edx] + movq mm4,[edi] + psrlw mm0,1 + psrlw mm1,1 + psrlw mm4,1 + pand mm0,mm5 + pand mm1,mm5 + pand mm4,mm5 + paddusb mm0,mm1 + paddusb mm0,mm6 + psrlw mm0,1 + pand mm0,mm5 + paddusb mm4,mm0 + paddusb mm4,mm6 + movq [edi],mm4 + add edi,ebx + add esi,ebx + dec ecx + jnz .recvac1 + emms + pop edx + pop ebx + pop ecx + pop edi + pop esi + ret + +%assign RegisterStorageSize 20 +%assign rfp LocalFrameSize + RegisterStorageSize + 4 +%assign bp LocalFrameSize + RegisterStorageSize + 8 +%assign iincr LocalFrameSize + RegisterStorageSize + 12 + +; FIXME clipping needs to be done + + align 16 +add_block_mmx: + push esi + push edi + push ecx + push ebx + push edx + mov esi, [esp+bp] + mov edi, [esp+rfp] + mov ebx, [esp+iincr] +; movq mm7, [PLUS_384] + mov ecx,8 + pxor mm2,mm2 ; clear +%rep 8 + movq mm0, [edi] ; get dest + movq mm1,mm0 + punpcklbw mm0,mm2 + punpckhbw mm1,mm2 + paddsw mm0, [esi] + paddsw mm1, [esi+8] +; paddsw mm0, mm7 +; paddsw mm1, mm7 + packuswb mm0,mm1 + movq [edi], mm0 + add edi,ebx + add esi,16 +%endrep + emms + pop edx + pop ebx + pop ecx + pop edi + pop esi + ret + + align 16 +set_block_mmx: + push esi + push edi + push ecx + push ebx + push edx + mov esi, [esp+bp] + mov edi, [esp+rfp] + mov ebx, [esp+iincr] + movq mm7, [PLUS_128] +%rep 4 + movq mm0, [esi] + movq mm1, [esi+8] + paddsw mm0, mm7 + movq mm2, [esi+16] + paddsw mm1, mm7 + movq mm3, [esi+24] + paddsw mm2, mm7 + packuswb mm0, mm1 + paddsw mm3, mm7 + movq [edi], mm0 + packuswb mm2, mm3 + add edi, ebx + add esi, 32 + movq [edi], mm2 + add edi, ebx +%endrep + emms + pop edx + pop ebx + pop ecx + pop edi + pop esi + ret + + diff --git a/core/multimedia/opieplayer/libmpeg3/video/reconstruct.c b/core/multimedia/opieplayer/libmpeg3/video/reconstruct.c new file mode 100644 index 0000000..531f9c0 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/reconstruct.c @@ -0,0 +1,1290 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include + +#ifdef HAVE_MMX + +#ifdef HAVE_3Dnow +static inline void recva_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + __asm__( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq (%4), %%mm2\n" /* 8 s +lx */ + "movq 8(%4), %%mm3\n" /* 8 s +lx **/ + + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "pavgusb %%mm3, %%mm1\n" + + "movq (%2), %%mm2\n" /* 8 d */ + "movq 8(%2), %%mm3\n" /* 8 d */ + "pavgusb %%mm2, %%mm0\n" + "addl %3, %4\n" + "pavgusb %%mm3, %%mm1\n" + + "movq %%mm0, (%2)\n" + "movq %%mm1, 8(%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +static inline void recvac_mmx(unsigned char *s, unsigned char *d, int lx,int lx2, int h) +{ + __asm__( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%4), %%mm2\n" /* 8 s +lx */ + "addl %3, %1\n" + "pavgusb %%mm2, %%mm0\n" + "movq (%2), %%mm3\n" /* 8 d */ + "addl %3, %4\n" + "pavgusb %%mm3, %%mm0\n" + "movq %%mm0, (%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +static inline void rech_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s */ + "movq 9(%1), %%mm3\n" /* 8 s */ + + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "pavgusb %%mm3, %%mm1\n" + + "movq %%mm0, (%2)\n" + "movq %%mm1, 8(%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + +static inline void rechc_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s +1 */ + "addl %3, %1\n" + "pavgusb %%mm2, %%mm0\n" + "movq %%mm0, (%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + +static inline void recha_mmx(unsigned char *s, unsigned char *d,int lx2, int h) +{ + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s */ + "movq 9(%1), %%mm3\n" /* 8 s */ + + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "pavgusb %%mm3, %%mm1\n" + + "movq (%2), %%mm2\n" /* 8 d */ + "movq 8(%2), %%mm3\n" /* 8 d */ + "pavgusb %%mm2, %%mm0\n" + "pavgusb %%mm3, %%mm1\n" + + "movq %%mm0, (%2)\n" + "movq %%mm1, 8(%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + +static inline void rechac_mmx(unsigned char *s,unsigned char *d, int lx2, int h) +{ + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s */ + + "addl %3, %1\n" + "pavgusb %%mm2, %%mm0\n" + + "movq (%2), %%mm1\n" /* 8 d */ + "pavgusb %%mm1, %%mm0\n" + + "movq %%mm0, (%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + +static inline void rec4_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + __asm__ __volatile__( + "movq (%1), %%mm0\n" /* 8 s */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s +1*/ + "movq 9(%1), %%mm3\n" /* 8 s +1*/ + ".align 8\n" + "1:" + "movq (%4), %%mm4\n" /* 8 s+lx */ + "pavgusb %%mm2, %%mm0\n" + "movq 8(%4), %%mm5\n" /* 8 s+lx */ + "pavgusb %%mm3, %%mm1\n" + + "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ + "pavgusb %%mm4, %%mm0\n" + "movq 9(%4), %%mm7\n" /* 8 s+lx +1*/ + "pavgusb %%mm5, %%mm1\n" + + "pavgusb %%mm6, %%mm0\n" + "addl %3, %4\n" + "pavgusb %%mm7, %%mm1\n" + "movq %%mm0, (%2)\n" + "movq %%mm6, %%mm2\n" + "movq %%mm7, %%mm3\n" + "movq %%mm1, 8(%2)\n" + "movq %%mm4, %%mm0\n" + "movq %%mm5, %%mm1\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +static inline void rec4c_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + __asm__ __volatile__( + "movq (%1), %%mm0\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s +1*/ + ".align 8\n" + "1:" + "movq (%4), %%mm4\n" /* 8 s+lx */ + "pavgusb %%mm2, %%mm0\n" + + "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ + "pavgusb %%mm4, %%mm0\n" + + "addl %3, %4\n" + "pavgusb %%mm6, %%mm0\n" + "movq %%mm0, (%2)\n" + "movq %%mm6, %%mm2\n" + "movq %%mm4, %%mm0\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +static inline void rec4a_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + __asm__ __volatile__( + "movq (%1), %%mm0\n" /* 8 s */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s +1*/ + "movq 9(%1), %%mm3\n" /* 8 s +1*/ + ".align 8\n" + "1:" + "movq (%4), %%mm4\n" /* 8 s+lx */ + "pavgusb %%mm2, %%mm0\n" + "movq 8(%4), %%mm5\n" /* 8 s+lx */ + "pavgusb %%mm3, %%mm1\n" + + "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ + "pavgusb %%mm4, %%mm0\n" + "movq 9(%4), %%mm7\n" /* 8 s+lx +1*/ + "pavgusb %%mm5, %%mm1\n" + "movq (%2), %%mm2\n" + "pavgusb %%mm6, %%mm0\n" + "movq 8(%2), %%mm3\n" + + "pavgusb %%mm2, %%mm0\n" + "addl %3, %4\n" + "pavgusb %%mm3, %%mm1\n" + "movq %%mm0, (%2)\n" + + "pavgusb %%mm7, %%mm1\n" + "movq %%mm6, %%mm2\n" + "movq %%mm7, %%mm3\n" + "movq %%mm1, 8(%2)\n" + "movq %%mm4, %%mm0\n" + "movq %%mm5, %%mm1\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +static inline void rec4ac_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + __asm__ __volatile__( + "movq (%1), %%mm0\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s +1*/ + ".align 8\n" + "1:" + "movq (%4), %%mm4\n" /* 8 s+lx */ + "pavgusb %%mm2, %%mm0\n" + + "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ + "pavgusb %%mm4, %%mm0\n" + "movq (%2), %%mm1\n" /* 8 d */ + "pavgusb %%mm6, %%mm0\n" + "addl %3, %4\n" + "pavgusb %%mm1, %%mm0\n" + "movq %%mm6, %%mm2\n" + "movq %%mm0, (%2)\n" + "movq %%mm4, %%mm0\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +#else // HAVE_3DNOW + static LONGLONG ADD_1 = 0x0101010101010101LL; + static LONGLONG MASK_AND = 0x7f7f7f7f7f7f7f7fLL; +#endif + +static inline void rec_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ + __asm__ __volatile__( + ".align 8\n" + "1:\t" + "movq ( %1 ), %%mm0\n" /* 8 s */ + "movq 8( %1 ), %%mm2\n" /* 16 s */ + "movq %%mm0, ( %2 )\n" + "addl %3, %1\n" + "movq %%mm2, 8( %2 )\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + + +static inline void recc_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ + __asm__ __volatile__( + ".align 8\n" + "1:\t" + "movq ( %1 ), %%mm0\n" + "addl %3, %1\n" + "movq %%mm0, ( %2 )\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + + +static inline void reca_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ +#ifdef HAVE_3Dnow + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%2), %%mm2\n" /* 8 d */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 8(%2), %%mm3\n" /* 8 d */ + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "pavgusb %%mm3, %%mm1\n" + + "movq %%mm0, (%2)\n" + "movq %%mm1, 8(%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +#else /* No 3dnow */ + __asm__ ( + "movq MASK_AND, %%mm5\n" + "movq ADD_1, %%mm6\n" + "1:\t" + "movq (%1),%%mm0\n" /* Load 16 pixels from each row */ + "movq (%2),%%mm1\n" + "movq 8(%1),%%mm2\n" + "movq 8(%2),%%mm3\n" + "psrlw $1,%%mm0\n" /* Shift pixels down */ + "psrlw $1,%%mm1\n" + "pand %%mm5,%%mm0\n" /* Zero out significant bit */ + "psrlw $1,%%mm2\n" + "pand %%mm5,%%mm1\n" + "psrlw $1,%%mm3\n" + "pand %%mm5,%%mm2\n" + "paddusb %%mm1,%%mm0\n" /* Add pixels */ + "pand %%mm5,%%mm3\n" + "paddusb %%mm3,%%mm2\n" + "paddusb %%mm6,%%mm0\n" /* Add 1 to results */ + "paddusb %%mm6,%%mm2\n" + "movq %%mm0,(%2)\n" + "addl %3,%1\n" + "movq %%mm2, 8(%2)\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +#endif +} + + +static inline void recac_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ +#ifdef HAVE_3Dnow + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%2), %%mm2\n" /* 8 d */ + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "movq %%mm0, (%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +#else /* No 3dnow */ + __asm__ ( + "movq MASK_AND, %%mm5\n" + "movq ADD_1, %%mm6\n" + "1:\t" + "movq (%1),%%mm0\n" + "movq (%2),%%mm1\n" + "psrlw $1,%%mm0\n" + "psrlw $1,%%mm1\n" + "pand %%mm5,%%mm0\n" + "pand %%mm5,%%mm1\n" + "paddusb %%mm1,%%mm0\n" + "paddusb %%mm6,%%mm0\n" + "addl %3,%1\n" + "movq %%mm0,(%2)\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +#endif +} + + +static inline void recv_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ +#ifdef HAVE_3Dnow + __asm__( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%4), %%mm2\n" /* 8 s +lx */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 8(%4), %%mm3\n" /* 8 s +lx **/ + + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "pavgusb %%mm3, %%mm1\n" + + "movq %%mm0, (%2)\n" + "addl %3, %4\n" + "movq %%mm1, 8(%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +#else + __asm__ ( + "movq MASK_AND, %%mm5\n" + "movq ADD_1, %%mm6\n" + "1:\t" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%4), %%mm1\n" /* 8 s +lx */ + "movq 8(%1), %%mm2\n" /* 8 s */ + "movq 8(%4), %%mm3\n" /* 8 s +lx **/ + "psrlw $1,%%mm0\n" + "psrlw $1,%%mm1\n" + "pand %%mm5,%%mm0\n" + "psrlw $1,%%mm2\n" + "pand %%mm5,%%mm1\n" + "psrlw $1,%%mm3\n" + "pand %%mm5,%%mm2\n" + "paddusb %%mm1,%%mm0\n" + "pand %%mm5,%%mm3\n" + "paddusb %%mm3,%%mm2\n" + "paddusb %%mm6,%%mm0\n" + "paddusb %%mm6,%%mm2\n" + "movq %%mm0,(%2)\n" + "addl %3,%1\n" + "movq %%mm2, 8(%2)\n" + "addl %3,%4\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +#endif +} + + +static inline void recvc_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ +#ifdef HAVE_3Dnow + __asm__( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%4), %%mm2\n" /* 8 s +lx */ + "addl %3, %1\n" + "pavgusb %%mm2, %%mm0\n" + "addl %3, %4\n" + "movq %%mm0, (%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +#else + __asm__ ( + "movq MASK_AND, %%mm5\n" + "movq ADD_1, %%mm6\n" + "1:\t" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%4), %%mm1\n" /* 8 s +lx */ + "psrlw $1,%%mm0\n" + "psrlw $1,%%mm1\n" + "pand %%mm5,%%mm0\n" + "pand %%mm5,%%mm1\n" + "paddusb %%mm1,%%mm0\n" + "addl %3,%1\n" + "paddusb %%mm6,%%mm0\n" + "addl %3,%4\n" + "movq %%mm0,(%2)\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +#endif +} + +#endif // HAVE_MMX + +static inline void rec(unsigned char *s, unsigned char *d, int lx2, int h) +{ + int j; + for(j = 0; j < h; j++, s += lx2, d += lx2) + { + d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; d[3] = s[3]; + d[4] = s[4]; d[5] = s[5]; d[6] = s[6]; d[7] = s[7]; + d[8] = s[8]; d[9] = s[9]; d[10] = s[10]; d[11] = s[11]; + d[12] = s[12]; d[13] = s[13]; d[14] = s[14]; d[15] = s[15]; + } +} + + + +static inline void recc(unsigned char *s, unsigned char *d, int lx2, int h) +{ + int j; + for(j = 0; j < h; j++, s += lx2, d += lx2) + { + d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; d[3] = s[3]; + d[4] = s[4]; d[5] = s[5]; d[6] = s[6]; d[7] = s[7]; + } +} + +static inline void reca(unsigned char *s, unsigned char *d, int lx2, int h) +{ + int j; + for(j = 0; j < h; j++, s +=lx2, d +=lx2) + { + d[0] = (unsigned int)(d[0] + s[0] + 1) >> 1; + d[1] = (unsigned int)(d[1] + s[1] + 1) >> 1; + d[2] = (unsigned int)(d[2] + s[2] + 1) >> 1; + d[3] = (unsigned int)(d[3] + s[3] + 1) >> 1; + d[4] = (unsigned int)(d[4] + s[4] + 1) >> 1; + d[5] = (unsigned int)(d[5] + s[5] + 1) >> 1; + d[6] = (unsigned int)(d[6] + s[6] + 1) >> 1; + d[7] = (unsigned int)(d[7] + s[7] + 1) >> 1; + d[8] = (unsigned int)(d[8] + s[8] + 1) >> 1; + d[9] = (unsigned int)(d[9] + s[9] + 1) >> 1; + d[10] = (unsigned int)(d[10] + s[10] + 1) >> 1; + d[11] = (unsigned int)(d[11] + s[11] + 1) >> 1; + d[12] = (unsigned int)(d[12] + s[12] + 1) >> 1; + d[13] = (unsigned int)(d[13] + s[13] + 1) >> 1; + d[14] = (unsigned int)(d[14] + s[14] + 1) >> 1; + d[15] = (unsigned int)(d[15] + s[15] + 1) >> 1; + } +} + +static inline void recac(unsigned char *s, unsigned char *d, int lx2, int h) +{ + int j; + for(j = 0; j < h; j++, s += lx2, d += lx2) + { + d[0] = (unsigned int)(d[0] + s[0] + 1)>>1; + d[1] = (unsigned int)(d[1] + s[1] + 1)>>1; + d[2] = (unsigned int)(d[2] + s[2] + 1)>>1; + d[3] = (unsigned int)(d[3] + s[3] + 1)>>1; + d[4] = (unsigned int)(d[4] + s[4] + 1)>>1; + d[5] = (unsigned int)(d[5] + s[5] + 1)>>1; + d[6] = (unsigned int)(d[6] + s[6] + 1)>>1; + d[7] = (unsigned int)(d[7] + s[7] + 1)>>1; + } +} + +static inline void recv_(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp,*sp,*sp2; + int j; + sp = s; + sp2 = s + lx; + dp = d; + for(j = 0; j < h; j++) + { + dp[0] = (unsigned int)(sp[0] + sp2[0] + 1) >> 1; + dp[1] = (unsigned int)(sp[1] + sp2[1] + 1) >> 1; + dp[2] = (unsigned int)(sp[2] + sp2[2] + 1) >> 1; + dp[3] = (unsigned int)(sp[3] + sp2[3] + 1) >> 1; + dp[4] = (unsigned int)(sp[4] + sp2[4] + 1) >> 1; + dp[5] = (unsigned int)(sp[5] + sp2[5] + 1) >> 1; + dp[6] = (unsigned int)(sp[6] + sp2[6] + 1) >> 1; + dp[7] = (unsigned int)(sp[7] + sp2[7] + 1) >> 1; + dp[8] = (unsigned int)(sp[8] + sp2[8] + 1) >> 1; + dp[9] = (unsigned int)(sp[9] + sp2[9] + 1) >> 1; + dp[10] = (unsigned int)(sp[10] + sp2[10] + 1) >> 1; + dp[11] = (unsigned int)(sp[11] + sp2[11] + 1) >> 1; + dp[12] = (unsigned int)(sp[12] + sp2[12] + 1) >> 1; + dp[13] = (unsigned int)(sp[13] + sp2[13] + 1) >> 1; + dp[14] = (unsigned int)(sp[14] + sp2[14] + 1) >> 1; + dp[15] = (unsigned int)(sp[15] + sp2[15] + 1) >> 1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + +static inline void recvc(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp,*sp,*sp2; + int j; + + sp = s; + sp2 = s+lx; + dp = d; + for(j = 0; j < h; j++) + { + dp[0] = (unsigned int)(sp[0]+sp2[0]+1)>>1; + dp[1] = (unsigned int)(sp[1]+sp2[1]+1)>>1; + dp[2] = (unsigned int)(sp[2]+sp2[2]+1)>>1; + dp[3] = (unsigned int)(sp[3]+sp2[3]+1)>>1; + dp[4] = (unsigned int)(sp[4]+sp2[4]+1)>>1; + dp[5] = (unsigned int)(sp[5]+sp2[5]+1)>>1; + dp[6] = (unsigned int)(sp[6]+sp2[6]+1)>>1; + dp[7] = (unsigned int)(sp[7]+sp2[7]+1)>>1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void recva(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp,*sp,*sp2; + int j; + + sp = s; + sp2 = s+lx; + dp = d; + for (j=0; j>1) + 1)>>1; + dp[1] = (dp[1] + ((unsigned int)(sp[1]+sp2[1]+1)>>1) + 1)>>1; + dp[2] = (dp[2] + ((unsigned int)(sp[2]+sp2[2]+1)>>1) + 1)>>1; + dp[3] = (dp[3] + ((unsigned int)(sp[3]+sp2[3]+1)>>1) + 1)>>1; + dp[4] = (dp[4] + ((unsigned int)(sp[4]+sp2[4]+1)>>1) + 1)>>1; + dp[5] = (dp[5] + ((unsigned int)(sp[5]+sp2[5]+1)>>1) + 1)>>1; + dp[6] = (dp[6] + ((unsigned int)(sp[6]+sp2[6]+1)>>1) + 1)>>1; + dp[7] = (dp[7] + ((unsigned int)(sp[7]+sp2[7]+1)>>1) + 1)>>1; + dp[8] = (dp[8] + ((unsigned int)(sp[8]+sp2[8]+1)>>1) + 1)>>1; + dp[9] = (dp[9] + ((unsigned int)(sp[9]+sp2[9]+1)>>1) + 1)>>1; + dp[10] = (dp[10] + ((unsigned int)(sp[10]+sp2[10]+1)>>1) + 1)>>1; + dp[11] = (dp[11] + ((unsigned int)(sp[11]+sp2[11]+1)>>1) + 1)>>1; + dp[12] = (dp[12] + ((unsigned int)(sp[12]+sp2[12]+1)>>1) + 1)>>1; + dp[13] = (dp[13] + ((unsigned int)(sp[13]+sp2[13]+1)>>1) + 1)>>1; + dp[14] = (dp[14] + ((unsigned int)(sp[14]+sp2[14]+1)>>1) + 1)>>1; + dp[15] = (dp[15] + ((unsigned int)(sp[15]+sp2[15]+1)>>1) + 1)>>1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void recvac(unsigned char *s, unsigned char *d, int lx,int lx2, int h){ + unsigned char *dp,*sp,*sp2; + int j; + + sp = s; + sp2 = s+lx; + dp = d; + for (j=0; j>1) + 1)>>1; + dp[1] = (dp[1] + ((unsigned int)(sp[1]+sp2[1]+1)>>1) + 1)>>1; + dp[2] = (dp[2] + ((unsigned int)(sp[2]+sp2[2]+1)>>1) + 1)>>1; + dp[3] = (dp[3] + ((unsigned int)(sp[3]+sp2[3]+1)>>1) + 1)>>1; + dp[4] = (dp[4] + ((unsigned int)(sp[4]+sp2[4]+1)>>1) + 1)>>1; + dp[5] = (dp[5] + ((unsigned int)(sp[5]+sp2[5]+1)>>1) + 1)>>1; + dp[6] = (dp[6] + ((unsigned int)(sp[6]+sp2[6]+1)>>1) + 1)>>1; + dp[7] = (dp[7] + ((unsigned int)(sp[7]+sp2[7]+1)>>1) + 1)>>1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void rech(unsigned char *s, unsigned char *d, int lx2, int h){ + unsigned char *dp,*sp; + unsigned int s1,s2; + int j; + + sp = s; + dp = d; + for (j=0; j>1; + dp[1] = (unsigned int)(s2+(s1=sp[2])+1)>>1; + dp[2] = (unsigned int)(s1+(s2=sp[3])+1)>>1; + dp[3] = (unsigned int)(s2+(s1=sp[4])+1)>>1; + dp[4] = (unsigned int)(s1+(s2=sp[5])+1)>>1; + dp[5] = (unsigned int)(s2+(s1=sp[6])+1)>>1; + dp[6] = (unsigned int)(s1+(s2=sp[7])+1)>>1; + dp[7] = (unsigned int)(s2+(s1=sp[8])+1)>>1; + dp[8] = (unsigned int)(s1+(s2=sp[9])+1)>>1; + dp[9] = (unsigned int)(s2+(s1=sp[10])+1)>>1; + dp[10] = (unsigned int)(s1+(s2=sp[11])+1)>>1; + dp[11] = (unsigned int)(s2+(s1=sp[12])+1)>>1; + dp[12] = (unsigned int)(s1+(s2=sp[13])+1)>>1; + dp[13] = (unsigned int)(s2+(s1=sp[14])+1)>>1; + dp[14] = (unsigned int)(s1+(s2=sp[15])+1)>>1; + dp[15] = (unsigned int)(s2+sp[16]+1)>>1; + sp+= lx2; + dp+= lx2; + } +} + + +static inline void rechc(unsigned char *s,unsigned char *d, int lx2, int h){ + unsigned char *dp,*sp; + unsigned int s1,s2; + int j; + + sp = s; + dp = d; + for (j=0; j>1; + dp[1] = (unsigned int)(s2+(s1=sp[2])+1)>>1; + dp[2] = (unsigned int)(s1+(s2=sp[3])+1)>>1; + dp[3] = (unsigned int)(s2+(s1=sp[4])+1)>>1; + dp[4] = (unsigned int)(s1+(s2=sp[5])+1)>>1; + dp[5] = (unsigned int)(s2+(s1=sp[6])+1)>>1; + dp[6] = (unsigned int)(s1+(s2=sp[7])+1)>>1; + dp[7] = (unsigned int)(s2+sp[8]+1)>>1; + sp+= lx2; + dp+= lx2; + } +} + +static inline void recha(unsigned char *s, unsigned char *d,int lx2, int h) +{ + unsigned char *dp,*sp; + unsigned int s1,s2; + int j; + + sp = s; + dp = d; + for (j = 0; j < h; j++) + { + s1 = sp[0]; + dp[0] = (dp[0] + ((unsigned int)(s1 + (s2 = sp[1]) + 1) >> 1) + 1) >> 1; + dp[1] = (dp[1] + ((unsigned int)(s2 + (s1 = sp[2]) + 1) >> 1) + 1) >> 1; + dp[2] = (dp[2] + ((unsigned int)(s1 + (s2 = sp[3]) + 1) >> 1) + 1) >> 1; + dp[3] = (dp[3] + ((unsigned int)(s2 + (s1 = sp[4]) + 1) >> 1) + 1) >> 1; + dp[4] = (dp[4] + ((unsigned int)(s1 + (s2 = sp[5]) + 1) >> 1) + 1) >> 1; + dp[5] = (dp[5] + ((unsigned int)(s2 + (s1 = sp[6]) + 1) >> 1) + 1) >> 1; + dp[6] = (dp[6] + ((unsigned int)(s1 + (s2 = sp[7]) + 1) >> 1) + 1) >> 1; + dp[7] = (dp[7] + ((unsigned int)(s2 + (s1 = sp[8]) + 1) >> 1) + 1) >> 1; + dp[8] = (dp[8] + ((unsigned int)(s1 + (s2 = sp[9]) + 1) >> 1) + 1) >> 1; + dp[9] = (dp[9] + ((unsigned int)(s2 + (s1 = sp[10]) + 1) >> 1) + 1) >> 1; + dp[10] = (dp[10] + ((unsigned int)(s1 + (s2 = sp[11]) + 1) >> 1) + 1) >> 1; + dp[11] = (dp[11] + ((unsigned int)(s2 + (s1 = sp[12]) + 1) >> 1) + 1) >> 1; + dp[12] = (dp[12] + ((unsigned int)(s1 + (s2 = sp[13]) + 1) >> 1) + 1) >> 1; + dp[13] = (dp[13] + ((unsigned int)(s2 + (s1 = sp[14]) + 1) >> 1) + 1) >> 1; + dp[14] = (dp[14] + ((unsigned int)(s1 + (s2 = sp[15]) + 1) >> 1) + 1) >> 1; + dp[15] = (dp[15] + ((unsigned int)(s2 + sp[16] + 1) >> 1) + 1) >> 1; + sp += lx2; + dp += lx2; + } +} + + +static inline void rechac(unsigned char *s,unsigned char *d, int lx2, int h) +{ + unsigned char *dp,*sp; + unsigned int s1,s2; + int j; + + sp = s; + dp = d; + for(j = 0; j < h; j++) + { + s1 = sp[0]; + dp[0] = (dp[0] + ((unsigned int)(s1 + (s2 = sp[1]) + 1) >> 1) + 1) >> 1; + dp[1] = (dp[1] + ((unsigned int)(s2 + (s1 = sp[2]) + 1) >> 1) + 1) >> 1; + dp[2] = (dp[2] + ((unsigned int)(s1 + (s2 = sp[3]) + 1) >> 1) + 1) >> 1; + dp[3] = (dp[3] + ((unsigned int)(s2 + (s1 = sp[4]) + 1) >> 1) + 1) >> 1; + dp[4] = (dp[4] + ((unsigned int)(s1 + (s2 = sp[5]) + 1) >> 1) + 1) >> 1; + dp[5] = (dp[5] + ((unsigned int)(s2 + (s1 = sp[6]) + 1) >> 1) + 1) >> 1; + dp[6] = (dp[6] + ((unsigned int)(s1 + (s2 = sp[7]) + 1) >> 1) + 1) >> 1; + dp[7] = (dp[7] + ((unsigned int)(s2 + sp[8] + 1) >> 1) + 1) >> 1; + sp += lx2; + dp += lx2; + } +} + + +static inline void rec4(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp,*sp,*sp2; + unsigned int s1,s2,s3,s4; + int j; + + sp = s; + sp2 = s+lx; + dp = d; + for (j=0; j>2; + dp[1] = (unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2; + dp[2] = (unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2; + dp[3] = (unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2; + dp[4] = (unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2; + dp[5] = (unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2; + dp[6] = (unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2; + dp[7] = (unsigned int)(s2+(s1=sp[8])+s4+(s3=sp2[8])+2)>>2; + dp[8] = (unsigned int)(s1+(s2=sp[9])+s3+(s4=sp2[9])+2)>>2; + dp[9] = (unsigned int)(s2+(s1=sp[10])+s4+(s3=sp2[10])+2)>>2; + dp[10] = (unsigned int)(s1+(s2=sp[11])+s3+(s4=sp2[11])+2)>>2; + dp[11] = (unsigned int)(s2+(s1=sp[12])+s4+(s3=sp2[12])+2)>>2; + dp[12] = (unsigned int)(s1+(s2=sp[13])+s3+(s4=sp2[13])+2)>>2; + dp[13] = (unsigned int)(s2+(s1=sp[14])+s4+(s3=sp2[14])+2)>>2; + dp[14] = (unsigned int)(s1+(s2=sp[15])+s3+(s4=sp2[15])+2)>>2; + dp[15] = (unsigned int)(s2+sp[16]+s4+sp2[16]+2)>>2; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void rec4c(unsigned char *s,unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp,*sp,*sp2; + unsigned int s1,s2,s3,s4; + int j; + + sp = s; + sp2 = s+lx; + dp = d; + for (j=0; j>2; + dp[1] = (unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2; + dp[2] = (unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2; + dp[3] = (unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2; + dp[4] = (unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2; + dp[5] = (unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2; + dp[6] = (unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2; + dp[7] = (unsigned int)(s2+sp[8]+s4+sp2[8]+2)>>2; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void rec4a(unsigned char *s,unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp=d, *sp=s, *sp2=s+lx; + unsigned int s1, s2, s3, s4; + int j; + +/* + sp = s; + sp2 = s+lx; + dp = d; +*/ + for (j=0; j>2) + 1)>>1; + dp[1] = (dp[1] + ((unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2) + 1)>>1; + dp[2] = (dp[2] + ((unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2) + 1)>>1; + dp[3] = (dp[3] + ((unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2) + 1)>>1; + dp[4] = (dp[4] + ((unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2) + 1)>>1; + dp[5] = (dp[5] + ((unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2) + 1)>>1; + dp[6] = (dp[6] + ((unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2) + 1)>>1; + dp[7] = (dp[7] + ((unsigned int)(s2+(s1=sp[8])+s4+(s3=sp2[8])+2)>>2) + 1)>>1; + dp[8] = (dp[8] + ((unsigned int)(s1+(s2=sp[9])+s3+(s4=sp2[9])+2)>>2) + 1)>>1; + dp[9] = (dp[9] + ((unsigned int)(s2+(s1=sp[10])+s4+(s3=sp2[10])+2)>>2) + 1)>>1; + dp[10] = (dp[10] + ((unsigned int)(s1+(s2=sp[11])+s3+(s4=sp2[11])+2)>>2) + 1)>>1; + dp[11] = (dp[11] + ((unsigned int)(s2+(s1=sp[12])+s4+(s3=sp2[12])+2)>>2) + 1)>>1; + dp[12] = (dp[12] + ((unsigned int)(s1+(s2=sp[13])+s3+(s4=sp2[13])+2)>>2) + 1)>>1; + dp[13] = (dp[13] + ((unsigned int)(s2+(s1=sp[14])+s4+(s3=sp2[14])+2)>>2) + 1)>>1; + dp[14] = (dp[14] + ((unsigned int)(s1+(s2=sp[15])+s3+(s4=sp2[15])+2)>>2) + 1)>>1; + dp[15] = (dp[15] + ((unsigned int)(s2+sp[16]+s4+sp2[16]+2)>>2) + 1)>>1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void rec4ac(unsigned char *s,unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp=d, *sp=s, *sp2=s+lx; + unsigned int s1,s2,s3,s4; + int j; + +/* + sp = s; + sp2 = s+lx; + dp = d; +*/ + for (j=0; j>2) + 1)>>1; + dp[1] = (dp[1] + ((unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2) + 1)>>1; + dp[2] = (dp[2] + ((unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2) + 1)>>1; + dp[3] = (dp[3] + ((unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2) + 1)>>1; + dp[4] = (dp[4] + ((unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2) + 1)>>1; + dp[5] = (dp[5] + ((unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2) + 1)>>1; + dp[6] = (dp[6] + ((unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2) + 1)>>1; + dp[7] = (dp[7] + ((unsigned int)(s2+sp[8]+s4+sp2[8]+2)>>2) + 1)>>1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + +static inline +void recon_comp(mpeg3video_t *video, + unsigned char *src, + unsigned char *dst, + int lx, + int lx2, + int w, + int h, + int x, + int y, + int dx, + int dy, + int addflag) +{ + int switcher; + unsigned char *s, *d; + +/* half pel scaling */ + switcher = (dx & 1) << 3 | (dy & 1) << 2 | w; + if(addflag) switcher |= 2; +/* origins */ + s = src + lx * (y + (dy >> 1)) + x + (dx >> 1); + d = dst + lx * y + x; + +// Accelerated functions +#ifdef HAVE_3Dnow + if(video->have_mmx) + { + switch(switcher) + { + case 0x3: reca_mmx(s, d, lx2, h); break; + case 0x2: recac_mmx(s, d, lx2, h); break; + case 0x1: rec_mmx(s, d, lx2, h); break; + case 0x0: recc_mmx(s, d, lx2, h); break; + case 0x7: recva_mmx(s, d, lx, lx2, h); break; + case 0x6: recvac_mmx(s, d, lx, lx2, h); break; + case 0x5: recv_mmx(s, d, lx, lx2, h); break; + case 0x4: recvc_mmx(s, d, lx, lx2, h); break; + case 0x9: rech_mmx(s, d, lx2, h); break; + case 0x8: rechc_mmx(s, d, lx2, h); break; + } + } + else +#endif + { + switch(switcher) + { + case 0x3: reca(s, d, lx2, h); break; + case 0x2: recac(s, d, lx2, h); break; + case 0x1: rec(s, d, lx2, h); break; + case 0x0: recc(s, d, lx2, h); break; + case 0x7: recva(s, d, lx, lx2, h); break; + case 0x6: recvac(s, d, lx, lx2, h); break; + case 0x5: recv_(s, d, lx, lx2, h); break; + case 0x4: recvc(s, d, lx, lx2, h); break; + case 0x9: rech(s, d, lx2, h); break; + case 0x8: rechc(s, d, lx2, h); break; + } + } + +// Unaccelerated functions + switch(switcher) + { + case 0xb: recha(s, d, lx2, h); break; + case 0xa: rechac(s, d, lx2, h); break; + case 0xf: rec4a(s, d, lx, lx2, h); break; + case 0xe: rec4ac(s, d, lx, lx2, h); break; + case 0xd: rec4(s, d, lx, lx2, h); break; + case 0xc: rec4c(s, d, lx, lx2, h); break; + } +} + +/* + unsigned char *src[]; * prediction source buffer * + int sfield; * prediction source field number (0 or 1) * + unsigned char *dst[]; * prediction destination buffer * + int dfield; * prediction destination field number (0 or 1)* + int lx,lx2; * horizontal offsets * + int w,h; * prediction block/sub-block width, height * + int x,y; * pixel co-ordinates of top-left sample in current MB * + int dx,dy; * horizontal, vertical motion vector * + int addflag; * add prediction error to prediction ? * +*/ +static void recon(mpeg3video_t *video, + unsigned char *src[], + int sfield, + unsigned char *dst[], + int dfield, + int lx, + int lx2, + int w, + int h, + int x, + int y, + int dx, + int dy, + int addflag) +{ + +/* Y */ + recon_comp(video, (src[0] + (sfield ? (lx2 >> 1) : 0)), + dst[0] + (dfield ? (lx2 >> 1) : 0), + lx, lx2, w, h, x, y, dx, dy, addflag); + + if(video->chroma_format != CHROMA444) + { + lx >>= 1; + dx /= 2; + lx2 >>= 1; + w = 0; + x >>= 1; + } + + if(video->chroma_format == CHROMA420) + { + h >>= 1; + dy /= 2; + y >>= 1; + } + +/* Cb */ + recon_comp(video, (src[1] + (sfield ? (lx2 >> 1) : 0)), + dst[1] + (dfield ? (lx2 >> 1) : 0), + lx, lx2, w, h, x, y, dx, dy, addflag); + +/* Cr */ + recon_comp(video, (src[2] + (sfield ? (lx2 >> 1) : 0)), + dst[2] + (dfield ? (lx2 >> 1) : 0), + lx, lx2, w, h, x, y, dx, dy, addflag); +} + +#define WIDTH 1 + +int mpeg3video_reconstruct(mpeg3video_t *video, + int bx, + int by, + int mb_type, + int motion_type, + int PMV[2][2][2], + int mv_field_sel[2][2], + int dmvector[2], + int stwtype) +{ + int currentfield; + unsigned char **predframe; + int DMV[2][2]; + int stwtop, stwbot; + + stwtop = stwtype % 3; /* 0:temporal, 1 : (spat+temp) / 2, 2 : spatial */ + stwbot = stwtype / 3; + + if((mb_type & MB_FORWARD) || (video->pict_type == P_TYPE)) + { + if(video->pict_struct == FRAME_PICTURE) + { + if((motion_type == MC_FRAME) || !(mb_type & MB_FORWARD)) + { +/* frame-based prediction */ + { + if(stwtop < 2) + recon(video, video->oldrefframe, 0, video->newframe, 0, + video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][0][0], PMV[0][0][1], stwtop); + + if(stwbot < 2) + recon(video, video->oldrefframe, 1, video->newframe, 1, + video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][0][0], PMV[0][0][1], stwbot); + } + } + else if(motion_type == MC_FIELD) /* field-based prediction */ + { +/* top field prediction */ + if(stwtop < 2) + recon(video, video->oldrefframe, mv_field_sel[0][0], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by >> 1, + PMV[0][0][0], PMV[0][0][1] >> 1, stwtop); + +/* bottom field prediction */ + if(stwbot < 2) + recon(video, video->oldrefframe, mv_field_sel[1][0], video->newframe, 1, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by >> 1, + PMV[1][0][0], PMV[1][0][1] >> 1, stwbot); + } + else if(motion_type == MC_DMV) + { +/* dual prime prediction */ +/* calculate derived motion vectors */ + mpeg3video_calc_dmv(video, + DMV, + dmvector, + PMV[0][0][0], + PMV[0][0][1] >> 1); + + if(stwtop < 2) + { +/* predict top field from top field */ + recon(video, video->oldrefframe, 0, video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by>>1, + PMV[0][0][0], PMV[0][0][1] >> 1, 0); + +/* predict and add to top field from bottom field */ + recon(video, video->oldrefframe, 1, video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by>>1, + DMV[0][0], DMV[0][1], 1); + } + + if(stwbot < 2) + { +/* predict bottom field from bottom field */ + recon(video, video->oldrefframe, 1, video->newframe, 1, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by>>1, + PMV[0][0][0], PMV[0][0][1]>>1, 0); + +/* predict and add to bottom field from top field */ + recon(video, video->oldrefframe, 0, video->newframe, 1, + video->coded_picture_width << 1, video->coded_picture_width<<1, WIDTH, 8, bx, by>>1, + DMV[1][0], DMV[1][1], 1); + } + } + else +/* invalid motion_type */ +/* fprintf(stderr, "reconstruct: invalid motion_type\n"); */ + ; + } + else + { +/* TOP_FIELD or BOTTOM_FIELD */ +/* field picture */ + currentfield = (video->pict_struct == BOTTOM_FIELD); + +/* determine which frame to use for prediction */ + if((video->pict_type == P_TYPE) && video->secondfield + && (currentfield != mv_field_sel[0][0])) + predframe = video->refframe; /* same frame */ + else + predframe = video->oldrefframe; /* previous frame */ + + if((motion_type == MC_FIELD) || !(mb_type & MB_FORWARD)) + { +/* field-based prediction */ + if(stwtop < 2) + recon(video, predframe,mv_field_sel[0][0],video->newframe,0, + video->coded_picture_width << 1,video->coded_picture_width << 1,WIDTH,16,bx,by, + PMV[0][0][0],PMV[0][0][1],stwtop); + } + else + if(motion_type == MC_16X8) + { + if(stwtop < 2) + { + recon(video, predframe, mv_field_sel[0][0], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][0][0], PMV[0][0][1], stwtop); + + /* determine which frame to use for lower half prediction */ + if((video->pict_type==P_TYPE) && video->secondfield + && (currentfield!=mv_field_sel[1][0])) + predframe = video->refframe; /* same frame */ + else + predframe = video->oldrefframe; /* previous frame */ + + recon(video, predframe, mv_field_sel[1][0], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by+8, + PMV[1][0][0], PMV[1][0][1], stwtop); + } + } + else + if(motion_type == MC_DMV) /* dual prime prediction */ + { + if(video->secondfield) + predframe = video->refframe; /* same frame */ + else + predframe = video->oldrefframe; /* previous frame */ + +/* calculate derived motion vectors */ + mpeg3video_calc_dmv(video, + DMV, + dmvector, + PMV[0][0][0], + PMV[0][0][1]); + +/* predict from field of same parity */ + recon(video, video->oldrefframe, currentfield, video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 16, bx, by, + PMV[0][0][0], PMV[0][0][1], 0); + +/* predict from field of opposite parity */ + recon(video, predframe, !currentfield, video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 16, bx, by, + DMV[0][0], DMV[0][1], 1); + } + else +/* invalid motion_type */ +/* fprintf(stderr, "reconstruct: invalid motion_type\n"); */ + ; + } + stwtop = stwbot = 1; + } + + if(mb_type & MB_BACKWARD) + { + if(video->pict_struct == FRAME_PICTURE) + { + if(motion_type == MC_FRAME) + { +/* frame-based prediction */ + if(stwtop < 2) + recon(video, video->refframe, 0, video->newframe, 0, + video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][1][0], PMV[0][1][1], stwtop); + + if(stwbot < 2) + recon(video, video->refframe, 1, video->newframe, 1, + video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][1][0], PMV[0][1][1], stwbot); + } + else + { +/* field-based prediction */ +/* top field prediction */ + if(stwtop < 2) + { + recon(video, video->refframe, mv_field_sel[0][1], video->newframe, 0, + (video->coded_picture_width << 1), (video->coded_picture_width<<1), WIDTH, 8, bx, (by >> 1), + PMV[0][1][0], (PMV[0][1][1] >> 1), stwtop); + } + +/* bottom field prediction */ + if(stwbot < 2) + { + recon(video, video->refframe, mv_field_sel[1][1], video->newframe, 1, (video->coded_picture_width << 1), + (video->coded_picture_width << 1), WIDTH, 8, bx, (by>>1), + PMV[1][1][0], (PMV[1][1][1]>>1), stwbot); + } + } + } + else + { +/* TOP_FIELD or BOTTOM_FIELD */ +/* field picture */ + if(motion_type == MC_FIELD) + { +/* field-based prediction */ + recon(video, video->refframe, mv_field_sel[0][1], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 16, bx, by, + PMV[0][1][0], PMV[0][1][1], stwtop); + } + else if(motion_type==MC_16X8) + { + recon(video, video->refframe, mv_field_sel[0][1], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][1][0], PMV[0][1][1], stwtop); + + recon(video, video->refframe, mv_field_sel[1][1], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by+8, + PMV[1][1][0], PMV[1][1][1], stwtop); + } + else +/* invalid motion_type */ +/* fprintf(stderr, "reconstruct: invalid motion_type\n"); */ + ; + } + } /* mb_type & MB_BACKWARD */ + return 0; +} + + diff --git a/core/multimedia/opieplayer/libmpeg3/video/seek.c b/core/multimedia/opieplayer/libmpeg3/video/seek.c new file mode 100644 index 0000000..04faba4 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/seek.c @@ -0,0 +1,233 @@ +#include "../mpeg3private.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include +#include + +unsigned int mpeg3bits_next_startcode(mpeg3_bits_t* stream) +{ +/* Perform forwards search */ + mpeg3bits_byte_align(stream); + +/* Perform search */ + while((mpeg3bits_showbits32_noptr(stream) >> 8) != MPEG3_PACKET_START_CODE_PREFIX && + !mpeg3bits_eof(stream)) + { + mpeg3bits_getbyte_noptr(stream); + } + return mpeg3bits_showbits32_noptr(stream); +} + +/* Line up on the beginning of the next code. */ +int mpeg3video_next_code(mpeg3_bits_t* stream, unsigned int code) +{ + while(!mpeg3bits_eof(stream) && + mpeg3bits_showbits32_noptr(stream) != code) + { + mpeg3bits_getbyte_noptr(stream); + } + return mpeg3bits_eof(stream); +} + +/* Line up on the beginning of the previous code. */ +int mpeg3video_prev_code(mpeg3_bits_t* stream, unsigned int code) +{ + while(!mpeg3bits_bof(stream) && + mpeg3bits_showbits_reverse(stream, 32) != code) + { + mpeg3bits_getbits_reverse(stream, 8); + } + return mpeg3bits_bof(stream); +} + +long mpeg3video_goptimecode_to_frame(mpeg3video_t *video) +{ +/* printf("mpeg3video_goptimecode_to_frame %d %d %d %d %f\n", */ +/* video->gop_timecode.hour, video->gop_timecode.minute, video->gop_timecode.second, video->gop_timecode.frame, video->frame_rate); */ + return (long)(video->gop_timecode.hour * 3600 * video->frame_rate + + video->gop_timecode.minute * 60 * video->frame_rate + + video->gop_timecode.second * video->frame_rate + + video->gop_timecode.frame) - 1 - video->first_frame; +} + +int mpeg3video_match_refframes(mpeg3video_t *video) +{ + unsigned char *dst, *src; + int i, j, size; + + for(i = 0; i < 3; i++) + { + if(video->newframe[i]) + { + if(video->newframe[i] == video->refframe[i]) + { + src = video->refframe[i]; + dst = video->oldrefframe[i]; + } + else + { + src = video->oldrefframe[i]; + dst = video->refframe[i]; + } + + if(i == 0) + size = video->coded_picture_width * video->coded_picture_height + 32 * video->coded_picture_width; + else + size = video->chrom_width * video->chrom_height + 32 * video->chrom_width; + + memcpy(dst, src, size); + } + } + return 0; +} + +int mpeg3video_seek(mpeg3video_t *video) +{ + long this_gop_start; + int result = 0; + int back_step; + int attempts; + mpeg3_t *file = video->file; + mpeg3_bits_t *vstream = video->vstream; + double percentage; + long frame_number; + int match_refframes = 1; + +/* Seek to a percentage */ + if(video->percentage_seek >= 0) + { + percentage = video->percentage_seek; + video->percentage_seek = -1; + mpeg3bits_seek_percentage(vstream, percentage); +// Go to previous I-frame + mpeg3bits_start_reverse(vstream); + result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); + if(!result) mpeg3bits_getbits_reverse(vstream, 32); + mpeg3bits_start_forward(vstream); + + if(mpeg3bits_tell_percentage(vstream) < 0) mpeg3bits_seek_percentage(vstream, 0); + +// Read up to the correct percentage + result = 0; + while(!result && mpeg3bits_tell_percentage(vstream) < percentage) + { + result = mpeg3video_read_frame_backend(video, 0); + if(match_refframes) + mpeg3video_match_refframes(video); + match_refframes = 0; + } + } + else +/* Seek to a frame */ + if(video->frame_seek >= 0) + { + frame_number = video->frame_seek; + video->frame_seek = -1; + if(frame_number < 0) frame_number = 0; + if(frame_number > video->maxframe) frame_number = video->maxframe; + +/* Seek to start of file */ + if(frame_number < 16) + { + video->repeat_count = video->current_repeat = 0; + mpeg3bits_seek_start(vstream); + video->framenum = 0; + result = mpeg3video_drop_frames(video, frame_number - video->framenum); + } + else + { +/* Seek to an I frame. */ + if((frame_number < video->framenum || frame_number - video->framenum > MPEG3_SEEK_THRESHOLD)) + { +/* Elementary stream */ + if(file->is_video_stream) + { + mpeg3_t *file = video->file; + mpeg3_vtrack_t *track = video->track; + long byte = (long)((float)(mpeg3demuxer_total_bytes(vstream->demuxer) / + track->total_frames) * + frame_number); + long minimum = 65535; + int done = 0; + +//printf("seek elementary %d\n", frame_number); +/* Get GOP just before frame */ + do + { + result = mpeg3bits_seek_byte(vstream, byte); + mpeg3bits_start_reverse(vstream); + if(!result) result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); + mpeg3bits_start_forward(vstream); + mpeg3bits_getbits(vstream, 8); + if(!result) result = mpeg3video_getgophdr(video); + this_gop_start = mpeg3video_goptimecode_to_frame(video); + +//printf("wanted %ld guessed %ld byte %ld result %d\n", frame_number, this_gop_start, byte, result); + if(labs(this_gop_start - frame_number) >= labs(minimum)) + done = 1; + else + { + minimum = this_gop_start - frame_number; + byte += (long)((float)(frame_number - this_gop_start) * + (float)(mpeg3demuxer_total_bytes(vstream->demuxer) / + track->total_frames)); + if(byte < 0) byte = 0; + } + }while(!result && !done); + +//printf("wanted %d guessed %d\n", frame_number, this_gop_start); + if(!result) + { + video->framenum = this_gop_start; + result = mpeg3video_drop_frames(video, frame_number - video->framenum); + } + } + else +/* System stream */ + { + mpeg3bits_seek_time(vstream, (double)frame_number / video->frame_rate); + percentage = mpeg3bits_tell_percentage(vstream); +//printf("seek frame %ld percentage %f byte %ld\n", frame_number, percentage, mpeg3bits_tell(vstream)); + mpeg3bits_start_reverse(vstream); + mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); + mpeg3bits_getbits_reverse(vstream, 32); + mpeg3bits_start_forward(vstream); +//printf("seek system 1 %f\n", (double)frame_number / video->frame_rate); + + while(!result && mpeg3bits_tell_percentage(vstream) < percentage) + { + result = mpeg3video_read_frame_backend(video, 0); + if(match_refframes) + mpeg3video_match_refframes(video); + +//printf("seek system 2 %f %f\n", mpeg3bits_tell_percentage(vstream) / percentage); + match_refframes = 0; + } +//printf("seek system 3 %f\n", (double)frame_number / video->frame_rate); + } + + video->framenum = frame_number; + } + else +// Drop frames + { + mpeg3video_drop_frames(video, frame_number - video->framenum); + } + } + } + + return result; +} + +int mpeg3video_drop_frames(mpeg3video_t *video, long frames) +{ + int result = 0; + long frame_number = video->framenum + frames; + +/* Read the selected number of frames and skip b-frames */ + while(!result && frame_number > video->framenum) + { + result = mpeg3video_read_frame_backend(video, frame_number - video->framenum); + } + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/slice.c b/core/multimedia/opieplayer/libmpeg3/video/slice.c new file mode 100644 index 0000000..90891b0 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/slice.c @@ -0,0 +1,702 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include "mpeg3videoprotos.h" +#include "slice.h" + +#include + +static ULONGLONG MMX_128 = 0x80008000800080LL; + +int mpeg3_new_slice_buffer(mpeg3_slice_buffer_t *slice_buffer) +{ + pthread_mutexattr_t mutex_attr; + slice_buffer->data = (unsigned char*)malloc(1024); + slice_buffer->buffer_size = 0; + slice_buffer->buffer_allocation = 1024; + slice_buffer->current_position = 0; + slice_buffer->bits_size = 0; + slice_buffer->bits = 0; + slice_buffer->done = 0; + pthread_mutexattr_init(&mutex_attr); + pthread_mutex_init(&(slice_buffer->completion_lock), &mutex_attr); + return 0; +} + +int mpeg3_delete_slice_buffer(mpeg3_slice_buffer_t *slice_buffer) +{ + free(slice_buffer->data); + pthread_mutex_destroy(&(slice_buffer->completion_lock)); + return 0; +} + +int mpeg3_expand_slice_buffer(mpeg3_slice_buffer_t *slice_buffer) +{ + int i; + unsigned char *new_buffer = + (unsigned char*)malloc(slice_buffer->buffer_allocation * 2); + for(i = 0; i < slice_buffer->buffer_size; i++) + new_buffer[i] = slice_buffer->data[i]; + free(slice_buffer->data); + slice_buffer->data = new_buffer; + slice_buffer->buffer_allocation *= 2; + return 0; +} + +/* limit coefficients to -2048..2047 */ + +/* move/add 8x8-Block from block[comp] to refframe */ + +static inline int mpeg3video_addblock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp, + int bx, + int by, + int dct_type, + int addflag) +{ + int cc, i, iincr; + unsigned char *rfp; + short *bp; + int spar = slice->sparse[comp]; +/* color component index */ + cc = (comp < 4) ? 0 : (comp & 1) + 1; + + if(cc == 0) + { +/* luminance */ + if(video->pict_struct == FRAME_PICTURE) + { + if(dct_type) + { +/* field DCT coding */ + rfp = video->newframe[0] + + video->coded_picture_width * (by + ((comp & 2) >> 1)) + bx + ((comp & 1) << 3); + iincr = (video->coded_picture_width << 1); + } + else + { +/* frame DCT coding */ + rfp = video->newframe[0] + + video->coded_picture_width * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3); + iincr = video->coded_picture_width; + } + } + else + { +/* field picture */ + rfp = video->newframe[0] + + (video->coded_picture_width << 1) * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3); + iincr = (video->coded_picture_width << 1); + } + } + else + { +/* chrominance */ + +/* scale coordinates */ + if(video->chroma_format != CHROMA444) bx >>= 1; + if(video->chroma_format == CHROMA420) by >>= 1; + if(video->pict_struct == FRAME_PICTURE) + { + if(dct_type && (video->chroma_format != CHROMA420)) + { +/* field DCT coding */ + rfp = video->newframe[cc] + + video->chrom_width * (by + ((comp & 2) >> 1)) + bx + (comp & 8); + iincr = (video->chrom_width << 1); + } + else + { +/* frame DCT coding */ + rfp = video->newframe[cc] + + video->chrom_width * (by + ((comp & 2) << 2)) + bx + (comp & 8); + iincr = video->chrom_width; + } + } + else + { +/* field picture */ + rfp = video->newframe[cc] + + (video->chrom_width << 1) * (by + ((comp & 2) << 2)) + bx + (comp & 8); + iincr = (video->chrom_width << 1); + } + } + + bp = slice->block[comp]; + + if(addflag) + { +#ifdef HAVE_MMX + if(video->have_mmx) + { + if(spar) + { + __asm__ __volatile__( + "movq (%2), %%mm6\n" /* 4 blockvals */ + "pxor %%mm4, %%mm4\n" + "punpcklwd %%mm6, %%mm6\n" + "punpcklwd %%mm6, %%mm6\n" + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 rindex1 */ + "movq %%mm0, %%mm2\n" + "punpcklbw %%mm4, %%mm0\n" + "punpckhbw %%mm4, %%mm2\n" + "paddw %%mm6, %%mm0\n" + "paddw %%mm6, %%mm2\n" + + "packuswb %%mm2, %%mm0\n" + "movq %%mm0, (%1)\n" + + "leal (%1, %3), %1\n" + "loop 1b\n" + : /* scr dest */ + : "c" (8),"r" (rfp), "r" (bp), "r" (iincr) + ); + } + else + { + __asm__ __volatile__( + "pxor %%mm4, %%mm4\n" + + ".align 8\n" + "1:" + "movq (%2), %%mm0\n" /* 8 rfp 0 1 2 3 4 5 6 7*/ + "movq (%1), %%mm6\n" /* 4 blockvals 0 1 2 3 */ + + "movq %%mm0, %%mm2\n" + "movq 8(%1), %%mm5\n" /* 4 blockvals 0 1 2 3 */ + "punpcklbw %%mm4, %%mm0\n" /* 0 2 4 6 */ + "punpckhbw %%mm4, %%mm2\n" /* 1 3 5 7 */ + + "paddw %%mm6, %%mm0\n" + "paddw %%mm5, %%mm2\n" + "packuswb %%mm2, %%mm0\n" + + "addl $16, %1\n" + "movq %%mm0, (%2)\n" + + "leal (%2,%3), %2\n" + "loop 1b\n" + : /* scr dest */ + : "c" (8),"r" (bp), "r" (rfp), "r" (iincr) + ); + } + } + else +#endif + for(i = 0; i < 8; i++) + { + rfp[0] = CLIP(bp[0] + rfp[0]); + rfp[1] = CLIP(bp[1] + rfp[1]); + rfp[2] = CLIP(bp[2] + rfp[2]); + rfp[3] = CLIP(bp[3] + rfp[3]); + rfp[4] = CLIP(bp[4] + rfp[4]); + rfp[5] = CLIP(bp[5] + rfp[5]); + rfp[6] = CLIP(bp[6] + rfp[6]); + rfp[7] = CLIP(bp[7] + rfp[7]); + rfp += iincr; + bp += 8; + } + } + else + { +#ifdef HAVE_MMX + if(video->have_mmx) + { + if(spar) + { + __asm__ __volatile__( + "movd (%2), %%mm0\n" /* " 0 0 0 v1" */ + "punpcklwd %%mm0, %%mm0\n" /* " 0 0 v1 v1" */ + "punpcklwd %%mm0, %%mm0\n" + "paddw MMX_128, %%mm0\n" + "packuswb %%mm0, %%mm0\n" + "leal (%0,%1,2), %%eax\n" + + "movq %%mm0, (%0, %1)\n" + "movq %%mm0, (%%eax)\n" + "leal (%%eax,%1,2), %0\n" + "movq %%mm0, (%%eax, %1)\n" + + "movq %%mm0, (%0)\n" + "leal (%0,%1,2), %%eax\n" + "movq %%mm0, (%0, %1)\n" + + "movq %%mm0, (%%eax)\n" + "movq %%mm0, (%%eax, %1)\n" + : + : "D" (rfp), "c" (iincr), "b" (bp) + : "eax"); + } + else + { + __asm__ __volatile__( + "movq MMX_128,%%mm4\n" + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" + "movq 8(%1), %%mm1\n" + "paddw %%mm4, %%mm0\n" + + "movq 16(%1), %%mm2\n" + "paddw %%mm4, %%mm1\n" + + "movq 24(%1), %%mm3\n" + "paddw %%mm4, %%mm2\n" + + "packuswb %%mm1, %%mm0\n" + "paddw %%mm4, %%mm3\n" + + "addl $32, %1\n" + "packuswb %%mm3, %%mm2\n" + + "movq %%mm0, (%2)\n" + + "movq %%mm2, (%2,%3)\n" + + "leal (%2,%3,2), %2\n" + "loop 1b\n" + : + : "c" (4), "r" (bp), "r" (rfp), "r" (iincr) + ); + } + } + else +#endif + for(i = 0; i < 8; i++) + { + rfp[0] = CLIP(bp[0] + 128); + rfp[1] = CLIP(bp[1] + 128); + rfp[2] = CLIP(bp[2] + 128); + rfp[3] = CLIP(bp[3] + 128); + rfp[4] = CLIP(bp[4] + 128); + rfp[5] = CLIP(bp[5] + 128); + rfp[6] = CLIP(bp[6] + 128); + rfp[7] = CLIP(bp[7] + 128); + rfp+= iincr; + bp += 8; + } + } + return 0; +} + +int mpeg3_decode_slice(mpeg3_slice_t *slice) +{ + mpeg3video_t *video = slice->video; + int comp; + int mb_type, cbp, motion_type = 0, dct_type; + int macroblock_address, mba_inc, mba_max; + int slice_vert_pos_ext; + unsigned int code; + int bx, by; + int dc_dct_pred[3]; + int mv_count, mv_format, mvscale; + int pmv[2][2][2], mv_field_sel[2][2]; + int dmv, dmvector[2]; + int qs; + int stwtype, stwclass; + int snr_cbp; + int i; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + +/* number of macroblocks per picture */ + mba_max = video->mb_width * video->mb_height; + +/* field picture has half as many macroblocks as frame */ + if(video->pict_struct != FRAME_PICTURE) + mba_max >>= 1; + +/* macroblock address */ + macroblock_address = 0; +/* first macroblock in slice is not skipped */ + mba_inc = 0; + slice->fault = 0; + + code = mpeg3slice_getbits(slice_buffer, 32); +/* decode slice header (may change quant_scale) */ + slice_vert_pos_ext = mpeg3video_getslicehdr(slice, video); + +/* reset all DC coefficient and motion vector predictors */ + dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; + pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; + pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; + + for(i = 0; + slice_buffer->current_position < slice_buffer->buffer_size; + i++) + { + if(mba_inc == 0) + { +/* Done */ + if(!mpeg3slice_showbits(slice_buffer, 23)) return 0; +/* decode macroblock address increment */ + mba_inc = mpeg3video_get_macroblock_address(slice); + + if(slice->fault) return 1; + + if(i == 0) + { +/* Get the macroblock_address */ + macroblock_address = ((slice_vert_pos_ext << 7) + (code & 255) - 1) * video->mb_width + mba_inc - 1; +/* first macroblock in slice: not skipped */ + mba_inc = 1; + } + } + + if(slice->fault) return 1; + + if(macroblock_address >= mba_max) + { +/* mba_inc points beyond picture dimensions */ + /*fprintf(stderr, "mpeg3_decode_slice: too many macroblocks in picture\n"); */ + return 1; + } + +/* not skipped */ + if(mba_inc == 1) + { + mpeg3video_macroblock_modes(slice, + video, + &mb_type, + &stwtype, + &stwclass, + &motion_type, + &mv_count, + &mv_format, + &dmv, + &mvscale, + &dct_type); + + if(slice->fault) return 1; + + if(mb_type & MB_QUANT) + { + qs = mpeg3slice_getbits(slice_buffer, 5); + + if(video->mpeg2) + slice->quant_scale = video->qscale_type ? mpeg3_non_linear_mquant_table[qs] : (qs << 1); + else + slice->quant_scale = qs; + + if(video->scalable_mode == SC_DP) +/* make sure quant_scale is valid */ + slice->quant_scale = slice->quant_scale; + } + +/* motion vectors */ + + +/* decode forward motion vectors */ + if((mb_type & MB_FORWARD) || ((mb_type & MB_INTRA) && video->conceal_mv)) + { + if(video->mpeg2) + mpeg3video_motion_vectors(slice, + video, + pmv, + dmvector, + mv_field_sel, + 0, + mv_count, + mv_format, + video->h_forw_r_size, + video->v_forw_r_size, + dmv, + mvscale); + else + mpeg3video_motion_vector(slice, + video, + pmv[0][0], + dmvector, + video->forw_r_size, + video->forw_r_size, + 0, + 0, + video->full_forw); + } + if(slice->fault) return 1; + +/* decode backward motion vectors */ + if(mb_type & MB_BACKWARD) + { + if(video->mpeg2) + mpeg3video_motion_vectors(slice, + video, + pmv, + dmvector, + mv_field_sel, + 1, + mv_count, + mv_format, + video->h_back_r_size, + video->v_back_r_size, + 0, + mvscale); + else + mpeg3video_motion_vector(slice, + video, + pmv[0][1], + dmvector, + video->back_r_size, + video->back_r_size, + 0, + 0, + video->full_back); + } + + if(slice->fault) return 1; + +/* remove marker_bit */ + if((mb_type & MB_INTRA) && video->conceal_mv) + mpeg3slice_flushbit(slice_buffer); + +/* macroblock_pattern */ + if(mb_type & MB_PATTERN) + { + cbp = mpeg3video_get_cbp(slice); + if(video->chroma_format == CHROMA422) + { +/* coded_block_pattern_1 */ + cbp = (cbp << 2) | mpeg3slice_getbits2(slice_buffer); + } + else + if(video->chroma_format == CHROMA444) + { +/* coded_block_pattern_2 */ + cbp = (cbp << 6) | mpeg3slice_getbits(slice_buffer, 6); + } + } + else + cbp = (mb_type & MB_INTRA) ? ((1 << video->blk_cnt) - 1) : 0; + + if(slice->fault) return 1; +/* decode blocks */ + mpeg3video_clearblock(slice, 0, video->blk_cnt); + for(comp = 0; comp < video->blk_cnt; comp++) + { + if(cbp & (1 << (video->blk_cnt - comp - 1))) + { + if(mb_type & MB_INTRA) + { + if(video->mpeg2) + mpeg3video_getmpg2intrablock(slice, video, comp, dc_dct_pred); + else + mpeg3video_getintrablock(slice, video, comp, dc_dct_pred); + } + else + { + if(video->mpeg2) + mpeg3video_getmpg2interblock(slice, video, comp); + else + mpeg3video_getinterblock(slice, video, comp); + } + if(slice->fault) return 1; + } + } + +/* reset intra_dc predictors */ + if(!(mb_type & MB_INTRA)) + dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; + +/* reset motion vector predictors */ + if((mb_type & MB_INTRA) && !video->conceal_mv) + { +/* intra mb without concealment motion vectors */ + pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; + pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; + } + + if((video->pict_type == P_TYPE) && !(mb_type & (MB_FORWARD | MB_INTRA))) + { +/* non-intra mb without forward mv in a P picture */ + pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; + +/* derive motion_type */ + if(video->pict_struct == FRAME_PICTURE) + motion_type = MC_FRAME; + else + { + motion_type = MC_FIELD; +/* predict from field of same parity */ + mv_field_sel[0][0] = (video->pict_struct == BOTTOM_FIELD); + } + } + + if(stwclass == 4) + { +/* purely spatially predicted macroblock */ + pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; + pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; + } + } + else + { +/* mba_inc!=1: skipped macroblock */ + mpeg3video_clearblock(slice, 0, video->blk_cnt); + +/* reset intra_dc predictors */ + dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; + +/* reset motion vector predictors */ + if(video->pict_type == P_TYPE) + pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; + +/* derive motion_type */ + if(video->pict_struct == FRAME_PICTURE) + motion_type = MC_FRAME; + else + { + motion_type = MC_FIELD; +/* predict from field of same parity */ + mv_field_sel[0][0] = mv_field_sel[0][1] = (video->pict_struct == BOTTOM_FIELD); + } + +/* skipped I are spatial-only predicted, */ +/* skipped P and B are temporal-only predicted */ + stwtype = (video->pict_type == I_TYPE) ? 8 : 0; + +/* clear MB_INTRA */ + mb_type &= ~MB_INTRA; + +/* no block data */ + cbp = 0; + } + + snr_cbp = 0; + +/* pixel coordinates of top left corner of current macroblock */ + bx = 16 * (macroblock_address % video->mb_width); + by = 16 * (macroblock_address / video->mb_width); + +/* motion compensation */ + if(!(mb_type & MB_INTRA)) + mpeg3video_reconstruct(video, + bx, + by, + mb_type, + motion_type, + pmv, + mv_field_sel, + dmvector, + stwtype); + +/* copy or add block data into picture */ + for(comp = 0; comp < video->blk_cnt; comp++) + { + if((cbp | snr_cbp) & (1 << (video->blk_cnt - 1 - comp))) + { +#ifdef HAVE_MMX + if(video->have_mmx) + IDCT_mmx(slice->block[comp]); + else +#endif + mpeg3video_idct_conversion(slice->block[comp]); + + mpeg3video_addblock(slice, + video, + comp, + bx, + by, + dct_type, + (mb_type & MB_INTRA) == 0); + } + } + +/* advance to next macroblock */ + macroblock_address++; + mba_inc--; + } + + return 0; +} + +void mpeg3_slice_loop(mpeg3_slice_t *slice) +{ + mpeg3video_t *video = slice->video; + int result = 1; + + while(!slice->done) + { + pthread_mutex_lock(&(slice->input_lock)); + + if(!slice->done) + { +/* Get a buffer to decode */ + result = 1; + pthread_mutex_lock(&(video->slice_lock)); + if(slice->buffer_step > 0) + { + while(slice->current_buffer <= slice->last_buffer) + { + if(!video->slice_buffers[slice->current_buffer].done && + slice->current_buffer <= slice->last_buffer) + { + result = 0; + break; + } + slice->current_buffer += slice->buffer_step; + } + } + else + { + while(slice->current_buffer >= slice->last_buffer) + { + if(!video->slice_buffers[slice->current_buffer].done && + slice->current_buffer >= slice->last_buffer) + { + result = 0; + break; + } + slice->current_buffer += slice->buffer_step; + } + } + +/* Got one */ + if(!result && slice->current_buffer >= 0 && slice->current_buffer < video->total_slice_buffers) + { + slice->slice_buffer = &(video->slice_buffers[slice->current_buffer]); + slice->slice_buffer->done = 1; + pthread_mutex_unlock(&(video->slice_lock)); + pthread_mutex_unlock(&(slice->input_lock)); + mpeg3_decode_slice(slice); + pthread_mutex_unlock(&(slice->slice_buffer->completion_lock)); + } + else + pthread_mutex_unlock(&(video->slice_lock)); + } + + pthread_mutex_unlock(&(slice->output_lock)); + } +} + +int mpeg3_new_slice_decoder(mpeg3video_t *video, mpeg3_slice_t *slice) +{ + pthread_attr_t attr; + //struct sched_param param; + pthread_mutexattr_t mutex_attr; + + slice->video = video; + slice->done = 0; + pthread_mutexattr_init(&mutex_attr); + pthread_mutex_init(&(slice->input_lock), &mutex_attr); + pthread_mutex_lock(&(slice->input_lock)); + pthread_mutex_init(&(slice->output_lock), &mutex_attr); + pthread_mutex_lock(&(slice->output_lock)); + + pthread_attr_init(&attr); + pthread_create(&(slice->tid), &attr, + (void * (*)(void *))mpeg3_slice_loop, slice); + + return 0; +} + +int mpeg3_delete_slice_decoder(mpeg3_slice_t *slice) +{ + slice->done = 1; + pthread_mutex_unlock(&(slice->input_lock)); + pthread_join(slice->tid, 0); + pthread_mutex_destroy(&(slice->input_lock)); + pthread_mutex_destroy(&(slice->output_lock)); + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/slice.h b/core/multimedia/opieplayer/libmpeg3/video/slice.h new file mode 100644 index 0000000..e36ffef --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/slice.h @@ -0,0 +1,194 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef SLICE_H +#define SLICE_H + +#ifndef _WIN32 +#include +#endif + +/* Array of these feeds the slice decoders */ +typedef struct +{ + unsigned char *data; /* Buffer for holding the slice data */ + int buffer_size; /* Size of buffer */ + int buffer_allocation; /* Space allocated for buffer */ + int current_position; /* Position in buffer */ + unsigned MPEG3_INT32 bits; + int bits_size; + pthread_mutex_t completion_lock; /* Lock slice until completion */ + int done; /* Signal for slice decoder to skip */ +} mpeg3_slice_buffer_t; + +/* Each slice decoder */ +typedef struct +{ + struct mpeg3video_rec *video; + mpeg3_slice_buffer_t *slice_buffer; + + int thread_number; /* Number of this thread */ + int current_buffer; /* Buffer this slice decoder is on */ + int buffer_step; /* Number of buffers to skip */ + int last_buffer; /* Last buffer this decoder should process */ + int fault; + int done; + int quant_scale; + int pri_brk; /* slice/macroblock */ + short block[12][64]; + int sparse[12]; + pthread_t tid; /* ID of thread */ + pthread_mutex_t input_lock, output_lock; +} mpeg3_slice_t; + +#define mpeg3slice_fillbits(buffer, nbits) \ + while(((mpeg3_slice_buffer_t*)(buffer))->bits_size < (nbits)) \ + { \ + if(((mpeg3_slice_buffer_t*)(buffer))->current_position < ((mpeg3_slice_buffer_t*)(buffer))->buffer_size) \ + { \ + ((mpeg3_slice_buffer_t*)(buffer))->bits <<= 8; \ + ((mpeg3_slice_buffer_t*)(buffer))->bits |= ((mpeg3_slice_buffer_t*)(buffer))->data[((mpeg3_slice_buffer_t*)(buffer))->current_position++]; \ + } \ + ((mpeg3_slice_buffer_t*)(buffer))->bits_size += 8; \ + } + +#define mpeg3slice_flushbits(buffer, nbits) \ + { \ + mpeg3slice_fillbits((buffer), (nbits)); \ + ((mpeg3_slice_buffer_t*)(buffer))->bits_size -= (nbits); \ + } + +#define mpeg3slice_flushbit(buffer) \ +{ \ + if(((mpeg3_slice_buffer_t*)(buffer))->bits_size) \ + ((mpeg3_slice_buffer_t*)(buffer))->bits_size--; \ + else \ + if(((mpeg3_slice_buffer_t*)(buffer))->current_position < ((mpeg3_slice_buffer_t*)(buffer))->buffer_size) \ + { \ + ((mpeg3_slice_buffer_t*)(buffer))->bits = \ + ((mpeg3_slice_buffer_t*)(buffer))->data[((mpeg3_slice_buffer_t*)(buffer))->current_position++]; \ + ((mpeg3_slice_buffer_t*)(buffer))->bits_size = 7; \ + } \ +} + +extern inline unsigned int mpeg3slice_getbit(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size) + return (buffer->bits >> (--buffer->bits_size)) & 0x1; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits = buffer->data[buffer->current_position++]; + buffer->bits_size = 7; + return (buffer->bits >> 7) & 0x1; + } + return 0; // WWA - stop warn +} + +extern inline unsigned int mpeg3slice_getbits2(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size >= 2) + return (buffer->bits >> (buffer->bits_size -= 2)) & 0x3; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits <<= 8; + buffer->bits |= buffer->data[buffer->current_position++]; + buffer->bits_size += 6; + return (buffer->bits >> buffer->bits_size) & 0x3; + } + return 0; // WWA - stop warn +} + +extern inline unsigned int mpeg3slice_getbyte(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size >= 8) + return (buffer->bits >> (buffer->bits_size -= 8)) & 0xff; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits <<= 8; + buffer->bits |= buffer->data[buffer->current_position++]; + return (buffer->bits >> buffer->bits_size) & 0xff; + } + return 0; // WWA - stop warn +} + + +extern inline unsigned int mpeg3slice_getbits(mpeg3_slice_buffer_t *slice_buffer, int bits) +{ + if(bits == 1) return mpeg3slice_getbit(slice_buffer); + mpeg3slice_fillbits(slice_buffer, bits); + return (slice_buffer->bits >> (slice_buffer->bits_size -= bits)) & (0xffffffff >> (32 - bits)); +} + +extern inline unsigned int mpeg3slice_showbits16(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size >= 16) + return (buffer->bits >> (buffer->bits_size - 16)) & 0xffff; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits <<= 16; + buffer->bits_size += 16; + buffer->bits |= (unsigned int)buffer->data[buffer->current_position++] << 8; + buffer->bits |= buffer->data[buffer->current_position++]; + return (buffer->bits >> (buffer->bits_size - 16)) & 0xffff; + } + return 0; // WWA - stop warn +} + +extern inline unsigned int mpeg3slice_showbits9(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size >= 9) + return (buffer->bits >> (buffer->bits_size - 9)) & 0x1ff; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits <<= 16; + buffer->bits_size += 16; + buffer->bits |= (unsigned int)buffer->data[buffer->current_position++] << 8; + buffer->bits |= buffer->data[buffer->current_position++]; + return (buffer->bits >> (buffer->bits_size - 9)) & 0x1ff; + } + return 0; // WWA - stop warn +} + +extern inline unsigned int mpeg3slice_showbits5(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size >= 5) + return (buffer->bits >> (buffer->bits_size - 5)) & 0x1f; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits <<= 8; + buffer->bits_size += 8; + buffer->bits |= buffer->data[buffer->current_position++]; + return (buffer->bits >> (buffer->bits_size - 5)) & 0x1f; + } + return 0; // WWA - stop warn +} + +extern inline unsigned int mpeg3slice_showbits(mpeg3_slice_buffer_t *slice_buffer, int bits) +{ + mpeg3slice_fillbits(slice_buffer, bits); + return (slice_buffer->bits >> (slice_buffer->bits_size - bits)) & (0xffffffff >> (32 - bits)); +} + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/vlc.c b/core/multimedia/opieplayer/libmpeg3/video/vlc.c new file mode 100644 index 0000000..4328d8a --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/vlc.c @@ -0,0 +1,421 @@ +#include "mpeg3video.h" +#include "vlc.h" + +/* variable length code tables */ + +/* Table B-3, mb_type in P-pictures, codes 001..1xx */ +mpeg3_VLCtab_t mpeg3_PMBtab0[8] = { + {ERROR,0}, + {MB_FORWARD,3}, + {MB_PATTERN,2}, {MB_PATTERN,2}, + {MB_FORWARD|MB_PATTERN,1}, {MB_FORWARD|MB_PATTERN,1}, + {MB_FORWARD|MB_PATTERN,1}, {MB_FORWARD|MB_PATTERN,1} +}; + +/* Table B-3, mb_type in P-pictures, codes 000001..00011x */ +mpeg3_VLCtab_t mpeg3_PMBtab1[8] = { + {ERROR,0}, + {MB_QUANT|MB_INTRA,6}, + {MB_QUANT|MB_PATTERN,5}, {MB_QUANT|MB_PATTERN,5}, + {MB_QUANT|MB_FORWARD|MB_PATTERN,5}, {MB_QUANT|MB_FORWARD|MB_PATTERN,5}, + {MB_INTRA,5}, {MB_INTRA,5} +}; + +/* Table B-4, mb_type in B-pictures, codes 0010..11xx */ +mpeg3_VLCtab_t mpeg3_BMBtab0[16] = { + {ERROR,0}, {ERROR,0}, + {MB_FORWARD,4}, + {MB_FORWARD|MB_PATTERN,4}, + {MB_BACKWARD,3}, {MB_BACKWARD,3}, + {MB_BACKWARD|MB_PATTERN,3}, {MB_BACKWARD|MB_PATTERN,3}, + {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, + {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2} +}; + +/* Table B-4, mb_type in B-pictures, codes 000001..00011x */ +mpeg3_VLCtab_t mpeg3_BMBtab1[8] = { + {ERROR,0}, + {MB_QUANT|MB_INTRA,6}, + {MB_QUANT|MB_BACKWARD|MB_PATTERN,6}, + {MB_QUANT|MB_FORWARD|MB_PATTERN,6}, + {MB_QUANT|MB_FORWARD|MB_BACKWARD|MB_PATTERN,5}, + {MB_QUANT|MB_FORWARD|MB_BACKWARD|MB_PATTERN,5}, + {MB_INTRA,5}, {MB_INTRA,5} +}; + +/* Table B-5, mb_type in spat. scal. I-pictures, codes 0001..1xxx */ +mpeg3_VLCtab_t mpeg3_spIMBtab[16] = { + {ERROR,0}, + {MB_CLASS4,4}, + {MB_QUANT|MB_INTRA,4}, + {MB_INTRA,4}, + {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, + {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, + {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, + {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, + {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, + {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1} +}; + +/* Table B-6, mb_type in spat. scal. P-pictures, codes 0010..11xx */ +mpeg3_VLCtab_t mpeg3_spPMBtab0[16] = +{ + {ERROR,0},{ERROR,0}, + {MB_FORWARD,4}, + {MB_WEIGHT|MB_FORWARD,4}, + {MB_QUANT|MB_FORWARD|MB_PATTERN,3}, {MB_QUANT|MB_FORWARD|MB_PATTERN,3}, + {MB_WEIGHT|MB_FORWARD|MB_PATTERN,3}, {MB_WEIGHT|MB_FORWARD|MB_PATTERN,3}, + {MB_FORWARD|MB_PATTERN,2}, {MB_FORWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_PATTERN,2}, {MB_FORWARD|MB_PATTERN,2}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2} +}; + +/* Table B-6, mb_type in spat. scal. P-pictures, codes 0000010..000111x */ +mpeg3_VLCtab_t mpeg3_spPMBtab1[16] = { + {ERROR,0},{ERROR,0}, + {MB_CLASS4|MB_QUANT|MB_PATTERN,7}, + {MB_CLASS4,7}, + {MB_PATTERN,7}, + {MB_CLASS4|MB_PATTERN,7}, + {MB_QUANT|MB_INTRA,7}, + {MB_INTRA,7}, + {MB_QUANT|MB_PATTERN,6}, {MB_QUANT|MB_PATTERN,6}, + {MB_WEIGHT|MB_QUANT|MB_PATTERN,6}, {MB_WEIGHT|MB_QUANT|MB_PATTERN,6}, + {MB_WEIGHT,6}, {MB_WEIGHT,6}, + {MB_WEIGHT|MB_PATTERN,6}, {MB_WEIGHT|MB_PATTERN,6} +}; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 0010..11xx */ +mpeg3_VLCtab_t mpeg3_spBMBtab0[14] = { + {MB_FORWARD,4}, + {MB_FORWARD|MB_PATTERN,4}, + {MB_BACKWARD,3}, {MB_BACKWARD,3}, + {MB_BACKWARD|MB_PATTERN,3}, {MB_BACKWARD|MB_PATTERN,3}, + {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, + {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2} +}; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 0000100..000111x */ +mpeg3_VLCtab_t mpeg3_spBMBtab1[12] = { + {MB_QUANT|MB_FORWARD|MB_PATTERN,7}, + {MB_QUANT|MB_BACKWARD|MB_PATTERN,7}, + {MB_INTRA,7}, + {MB_QUANT|MB_FORWARD|MB_BACKWARD|MB_PATTERN,7}, + {MB_WEIGHT|MB_FORWARD,6}, {MB_WEIGHT|MB_FORWARD,6}, + {MB_WEIGHT|MB_FORWARD|MB_PATTERN,6}, {MB_WEIGHT|MB_FORWARD|MB_PATTERN,6}, + {MB_WEIGHT|MB_BACKWARD,6}, {MB_WEIGHT|MB_BACKWARD,6}, + {MB_WEIGHT|MB_BACKWARD|MB_PATTERN,6}, {MB_WEIGHT|MB_BACKWARD|MB_PATTERN,6} +}; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 00000100x..000001111 */ +mpeg3_VLCtab_t mpeg3_spBMBtab2[8] = { + {MB_QUANT|MB_INTRA,8}, {MB_QUANT|MB_INTRA,8}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,8}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,8}, + {MB_WEIGHT|MB_QUANT|MB_BACKWARD|MB_PATTERN,9}, + {MB_CLASS4|MB_QUANT|MB_PATTERN,9}, + {MB_CLASS4,9}, + {MB_CLASS4|MB_PATTERN,9} +}; + +/* Table B-8, mb_type in spat. scal. B-pictures, codes 001..1xx */ +mpeg3_VLCtab_t mpeg3_SNRMBtab[8] = { + {ERROR,0}, + {0,3}, + {MB_QUANT|MB_PATTERN,2}, {MB_QUANT|MB_PATTERN,2}, + {MB_PATTERN,1}, {MB_PATTERN,1}, {MB_PATTERN,1}, {MB_PATTERN,1} +}; + +/* Table B-10, motion_code, codes 0001 ... 01xx */ +mpeg3_VLCtab_t mpeg3_MVtab0[8] = +{ {ERROR,0}, {3,3}, {2,2}, {2,2}, {1,1}, {1,1}, {1,1}, {1,1} +}; + +/* Table B-10, motion_code, codes 0000011 ... 000011x */ +mpeg3_VLCtab_t mpeg3_MVtab1[8] = +{ {ERROR,0}, {ERROR,0}, {ERROR,0}, {7,6}, {6,6}, {5,6}, {4,5}, {4,5} +}; + +/* Table B-10, motion_code, codes 0000001100 ... 000001011x */ +mpeg3_VLCtab_t mpeg3_MVtab2[12] = +{ {16,9}, {15,9}, {14,9}, {13,9}, + {12,9}, {11,9}, {10,8}, {10,8}, + {9,8}, {9,8}, {8,8}, {8,8} +}; + +/* Table B-9, coded_block_pattern, codes 01000 ... 111xx */ +mpeg3_VLCtab_t mpeg3_CBPtab0[32] = +{ {ERROR,0}, {ERROR,0}, {ERROR,0}, {ERROR,0}, + {ERROR,0}, {ERROR,0}, {ERROR,0}, {ERROR,0}, + {62,5}, {2,5}, {61,5}, {1,5}, {56,5}, {52,5}, {44,5}, {28,5}, + {40,5}, {20,5}, {48,5}, {12,5}, {32,4}, {32,4}, {16,4}, {16,4}, + {8,4}, {8,4}, {4,4}, {4,4}, {60,3}, {60,3}, {60,3}, {60,3} +}; + +/* Table B-9, coded_block_pattern, codes 00000100 ... 001111xx */ +mpeg3_VLCtab_t mpeg3_CBPtab1[64] = +{ {ERROR,0}, {ERROR,0}, {ERROR,0}, {ERROR,0}, + {58,8}, {54,8}, {46,8}, {30,8}, + {57,8}, {53,8}, {45,8}, {29,8}, {38,8}, {26,8}, {37,8}, {25,8}, + {43,8}, {23,8}, {51,8}, {15,8}, {42,8}, {22,8}, {50,8}, {14,8}, + {41,8}, {21,8}, {49,8}, {13,8}, {35,8}, {19,8}, {11,8}, {7,8}, + {34,7}, {34,7}, {18,7}, {18,7}, {10,7}, {10,7}, {6,7}, {6,7}, + {33,7}, {33,7}, {17,7}, {17,7}, {9,7}, {9,7}, {5,7}, {5,7}, + {63,6}, {63,6}, {63,6}, {63,6}, {3,6}, {3,6}, {3,6}, {3,6}, + {36,6}, {36,6}, {36,6}, {36,6}, {24,6}, {24,6}, {24,6}, {24,6} +}; + +/* Table B-9, coded_block_pattern, codes 000000001 ... 000000111 */ +mpeg3_VLCtab_t mpeg3_CBPtab2[8] = +{ {ERROR,0}, {0,9}, {39,9}, {27,9}, {59,9}, {55,9}, {47,9}, {31,9} +}; + +/* Table B-1, macroblock_address_increment, codes 00010 ... 011xx */ +mpeg3_VLCtab_t mpeg3_MBAtab1[16] = +{ {ERROR,0}, {ERROR,0}, {7,5}, {6,5}, {5,4}, {5,4}, {4,4}, {4,4}, + {3,3}, {3,3}, {3,3}, {3,3}, {2,3}, {2,3}, {2,3}, {2,3} +}; + +/* Table B-1, macroblock_address_increment, codes 00000011000 ... 0000111xxxx */ +mpeg3_VLCtab_t mpeg3_MBAtab2[104] = +{ + {33,11}, {32,11}, {31,11}, {30,11}, {29,11}, {28,11}, {27,11}, {26,11}, + {25,11}, {24,11}, {23,11}, {22,11}, {21,10}, {21,10}, {20,10}, {20,10}, + {19,10}, {19,10}, {18,10}, {18,10}, {17,10}, {17,10}, {16,10}, {16,10}, + {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, + {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, + {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, + {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, + {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, + {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, + {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, + {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, + {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, + {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7} +}; + +/* Table B-12, dct_dc_size_luminance, codes 00xxx ... 11110 */ +mpeg3_VLCtab_t mpeg3_DClumtab0[32] = +{ {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5}, {ERROR, 0} +}; + +/* Table B-12, dct_dc_size_luminance, codes 111110xxx ... 111111111 */ +mpeg3_VLCtab_t mpeg3_DClumtab1[16] = +{ {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, + {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10,9}, {11,9} +}; + +/* Table B-13, dct_dc_size_chrominance, codes 00xxx ... 11110 */ +mpeg3_VLCtab_t mpeg3_DCchromtab0[32] = +{ {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5}, {ERROR, 0} +}; + +/* Table B-13, dct_dc_size_chrominance, codes 111110xxxx ... 1111111111 */ +mpeg3_VLCtab_t mpeg3_DCchromtab1[32] = +{ {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, + {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, + {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, + {8, 8}, {8, 8}, {8, 8}, {8, 8}, {9, 9}, {9, 9}, {10,10}, {11,10} +}; + +/* Table B-14, DCT coefficients table zero, + * codes 0100 ... 1xxx (used for first (DC) coefficient) + */ +mpeg3_DCTtab_t mpeg3_DCTtabfirst[12] = +{ + {0,2,4}, {2,1,4}, {1,1,3}, {1,1,3}, + {0,1,1}, {0,1,1}, {0,1,1}, {0,1,1}, + {0,1,1}, {0,1,1}, {0,1,1}, {0,1,1} +}; + +/* Table B-14, DCT coefficients table zero, + * codes 0100 ... 1xxx (used for all other coefficients) + */ +mpeg3_DCTtab_t mpeg3_DCTtabnext[12] = +{ + {0,2,4}, {2,1,4}, {1,1,3}, {1,1,3}, + {64,0,2}, {64,0,2}, {64,0,2}, {64,0,2}, /* EOB */ + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2} +}; + +/* Table B-14, DCT coefficients table zero, + * codes 000001xx ... 00111xxx + */ +mpeg3_DCTtab_t mpeg3_DCTtab0[60] = +{ + {65,0,6}, {65,0,6}, {65,0,6}, {65,0,6}, /* Escape */ + {2,2,7}, {2,2,7}, {9,1,7}, {9,1,7}, + {0,4,7}, {0,4,7}, {8,1,7}, {8,1,7}, + {7,1,6}, {7,1,6}, {7,1,6}, {7,1,6}, + {6,1,6}, {6,1,6}, {6,1,6}, {6,1,6}, + {1,2,6}, {1,2,6}, {1,2,6}, {1,2,6}, + {5,1,6}, {5,1,6}, {5,1,6}, {5,1,6}, + {13,1,8}, {0,6,8}, {12,1,8}, {11,1,8}, + {3,2,8}, {1,3,8}, {0,5,8}, {10,1,8}, + {0,3,5}, {0,3,5}, {0,3,5}, {0,3,5}, + {0,3,5}, {0,3,5}, {0,3,5}, {0,3,5}, + {4,1,5}, {4,1,5}, {4,1,5}, {4,1,5}, + {4,1,5}, {4,1,5}, {4,1,5}, {4,1,5}, + {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, + {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5} +}; + +/* Table B-15, DCT coefficients table one, + * codes 000001xx ... 11111111 +*/ +mpeg3_DCTtab_t mpeg3_DCTtab0a[252] = +{ + {65,0,6}, {65,0,6}, {65,0,6}, {65,0,6}, /* Escape */ + {7,1,7}, {7,1,7}, {8,1,7}, {8,1,7}, + {6,1,7}, {6,1,7}, {2,2,7}, {2,2,7}, + {0,7,6}, {0,7,6}, {0,7,6}, {0,7,6}, + {0,6,6}, {0,6,6}, {0,6,6}, {0,6,6}, + {4,1,6}, {4,1,6}, {4,1,6}, {4,1,6}, + {5,1,6}, {5,1,6}, {5,1,6}, {5,1,6}, + {1,5,8}, {11,1,8}, {0,11,8}, {0,10,8}, + {13,1,8}, {12,1,8}, {3,2,8}, {1,4,8}, + {2,1,5}, {2,1,5}, {2,1,5}, {2,1,5}, + {2,1,5}, {2,1,5}, {2,1,5}, {2,1,5}, + {1,2,5}, {1,2,5}, {1,2,5}, {1,2,5}, + {1,2,5}, {1,2,5}, {1,2,5}, {1,2,5}, + {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, + {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, /* EOB */ + {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, + {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, + {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, + {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, + {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, + {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, + {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,4,5}, {0,4,5}, {0,4,5}, {0,4,5}, + {0,4,5}, {0,4,5}, {0,4,5}, {0,4,5}, + {0,5,5}, {0,5,5}, {0,5,5}, {0,5,5}, + {0,5,5}, {0,5,5}, {0,5,5}, {0,5,5}, + {9,1,7}, {9,1,7}, {1,3,7}, {1,3,7}, + {10,1,7}, {10,1,7}, {0,8,7}, {0,8,7}, + {0,9,7}, {0,9,7}, {0,12,8}, {0,13,8}, + {2,3,8}, {4,2,8}, {0,14,8}, {0,15,8} +}; + +/* Table B-14, DCT coefficients table zero, + * codes 0000001000 ... 0000001111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab1[8] = +{ + {16,1,10}, {5,2,10}, {0,7,10}, {2,3,10}, + {1,4,10}, {15,1,10}, {14,1,10}, {4,2,10} +}; + +/* Table B-15, DCT coefficients table one, + * codes 000000100x ... 000000111x + */ +mpeg3_DCTtab_t mpeg3_DCTtab1a[8] = +{ + {5,2,9}, {5,2,9}, {14,1,9}, {14,1,9}, + {2,4,10}, {16,1,10}, {15,1,9}, {15,1,9} +}; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 000000010000 ... 000000011111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab2[16] = +{ + {0,11,12}, {8,2,12}, {4,3,12}, {0,10,12}, + {2,4,12}, {7,2,12}, {21,1,12}, {20,1,12}, + {0,9,12}, {19,1,12}, {18,1,12}, {1,5,12}, + {3,3,12}, {0,8,12}, {6,2,12}, {17,1,12} +}; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 0000000010000 ... 0000000011111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab3[16] = +{ + {10,2,13}, {9,2,13}, {5,3,13}, {3,4,13}, + {2,5,13}, {1,7,13}, {1,6,13}, {0,15,13}, + {0,14,13}, {0,13,13}, {0,12,13}, {26,1,13}, + {25,1,13}, {24,1,13}, {23,1,13}, {22,1,13} +}; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 00000000010000 ... 00000000011111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab4[16] = +{ + {0,31,14}, {0,30,14}, {0,29,14}, {0,28,14}, + {0,27,14}, {0,26,14}, {0,25,14}, {0,24,14}, + {0,23,14}, {0,22,14}, {0,21,14}, {0,20,14}, + {0,19,14}, {0,18,14}, {0,17,14}, {0,16,14} +}; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 000000000010000 ... 000000000011111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab5[16] = +{ + {0,40,15}, {0,39,15}, {0,38,15}, {0,37,15}, + {0,36,15}, {0,35,15}, {0,34,15}, {0,33,15}, + {0,32,15}, {1,14,15}, {1,13,15}, {1,12,15}, + {1,11,15}, {1,10,15}, {1,9,15}, {1,8,15} +}; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 0000000000010000 ... 0000000000011111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab6[16] = +{ + {1,18,16}, {1,17,16}, {1,16,16}, {1,15,16}, + {6,3,16}, {16,2,16}, {15,2,16}, {14,2,16}, + {13,2,16}, {12,2,16}, {11,2,16}, {31,1,16}, + {30,1,16}, {29,1,16}, {28,1,16}, {27,1,16} +}; diff --git a/core/multimedia/opieplayer/libmpeg3/video/vlc.h b/core/multimedia/opieplayer/libmpeg3/video/vlc.h new file mode 100644 index 0000000..727040b --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/vlc.h @@ -0,0 +1,164 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef VLC_H +#define VLC_H + +/* variable length code tables */ + +typedef struct { + char val, len; +} mpeg3_VLCtab_t; + +typedef struct { + char run, level, len; +} mpeg3_DCTtab_t; + +/* Added 03/38/96 by Alex de Jong : avoid IRIX GNU warning */ +#ifdef ERROR +#undef ERROR +#define ERROR 99 +#endif + +/* Table B-3, mb_type in P-pictures, codes 001..1xx */ +extern mpeg3_VLCtab_t mpeg3_PMBtab0[8]; + +/* Table B-3, mb_type in P-pictures, codes 000001..00011x */ +extern mpeg3_VLCtab_t mpeg3_PMBtab1[8]; + +/* Table B-4, mb_type in B-pictures, codes 0010..11xx */ +extern mpeg3_VLCtab_t mpeg3_BMBtab0[16]; + +/* Table B-4, mb_type in B-pictures, codes 000001..00011x */ +extern mpeg3_VLCtab_t mpeg3_BMBtab1[8]; + +/* Table B-5, mb_type in spat. scal. I-pictures, codes 0001..1xxx */ +extern mpeg3_VLCtab_t mpeg3_spIMBtab[16]; + +/* Table B-6, mb_type in spat. scal. P-pictures, codes 0010..11xx */ +extern mpeg3_VLCtab_t mpeg3_spPMBtab0[16]; + +/* Table B-6, mb_type in spat. scal. P-pictures, codes 0000010..000111x */ +extern mpeg3_VLCtab_t mpeg3_spPMBtab1[16]; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 0010..11xx */ +extern mpeg3_VLCtab_t mpeg3_spBMBtab0[14]; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 0000100..000111x */ +extern mpeg3_VLCtab_t mpeg3_spBMBtab1[12]; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 00000100x..000001111 */ +extern mpeg3_VLCtab_t mpeg3_spBMBtab2[8]; + +/* Table B-8, mb_type in spat. scal. B-pictures, codes 001..1xx */ +extern mpeg3_VLCtab_t mpeg3_SNRMBtab[8]; + +/* Table B-10, motion_code, codes 0001 ... 01xx */ +extern mpeg3_VLCtab_t mpeg3_MVtab0[8]; + +/* Table B-10, motion_code, codes 0000011 ... 000011x */ +extern mpeg3_VLCtab_t mpeg3_MVtab1[8]; + +/* Table B-10, motion_code, codes 0000001100 ... 000001011x */ +extern mpeg3_VLCtab_t mpeg3_MVtab2[12]; + +/* Table B-9, coded_block_pattern, codes 01000 ... 111xx */ +extern mpeg3_VLCtab_t mpeg3_CBPtab0[32]; + +/* Table B-9, coded_block_pattern, codes 00000100 ... 001111xx */ +extern mpeg3_VLCtab_t mpeg3_CBPtab1[64]; + +/* Table B-9, coded_block_pattern, codes 000000001 ... 000000111 */ +extern mpeg3_VLCtab_t mpeg3_CBPtab2[8]; + +/* Table B-1, macroblock_address_increment, codes 00010 ... 011xx */ +extern mpeg3_VLCtab_t mpeg3_MBAtab1[16]; + +/* Table B-1, macroblock_address_increment, codes 00000011000 ... 0000111xxxx */ +extern mpeg3_VLCtab_t mpeg3_MBAtab2[104]; + +/* Table B-12, dct_dc_size_luminance, codes 00xxx ... 11110 */ +extern mpeg3_VLCtab_t mpeg3_DClumtab0[32]; + +/* Table B-12, dct_dc_size_luminance, codes 111110xxx ... 111111111 */ +extern mpeg3_VLCtab_t mpeg3_DClumtab1[16]; + +/* Table B-13, dct_dc_size_chrominance, codes 00xxx ... 11110 */ +extern mpeg3_VLCtab_t mpeg3_DCchromtab0[32]; + +/* Table B-13, dct_dc_size_chrominance, codes 111110xxxx ... 1111111111 */ +extern mpeg3_VLCtab_t mpeg3_DCchromtab1[32]; + +/* Table B-14, DCT coefficients table zero, + * codes 0100 ... 1xxx (used for first (DC) coefficient) + */ +extern mpeg3_DCTtab_t mpeg3_DCTtabfirst[12]; + +/* Table B-14, DCT coefficients table zero, + * codes 0100 ... 1xxx (used for all other coefficients) + */ +extern mpeg3_DCTtab_t mpeg3_DCTtabnext[12]; + +/* Table B-14, DCT coefficients table zero, + * codes 000001xx ... 00111xxx + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab0[60]; + +/* Table B-15, DCT coefficients table one, + * codes 000001xx ... 11111111 +*/ +extern mpeg3_DCTtab_t mpeg3_DCTtab0a[252]; + +/* Table B-14, DCT coefficients table zero, + * codes 0000001000 ... 0000001111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab1[8]; + +/* Table B-15, DCT coefficients table one, + * codes 000000100x ... 000000111x + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab1a[8]; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 000000010000 ... 000000011111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab2[16]; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 0000000010000 ... 0000000011111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab3[16]; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 00000000010000 ... 00000000011111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab4[16]; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 000000000010000 ... 000000000011111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab5[16]; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 0000000000010000 ... 0000000000011111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab6[16]; + + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/worksheet.c b/core/multimedia/opieplayer/libmpeg3/video/worksheet.c new file mode 100644 index 0000000..c5a0553 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/worksheet.c @@ -0,0 +1,30 @@ +#include +#include +#include + + +static LONGLONG mpeg3_MMX_601_Y_COEF = 0x0000004000400040; + +inline void mpeg3_601_mmx(unsigned long y, + unsigned long *output) +{ +asm(" +/* Output will be 0x00rrggbb */ + movd (%0), %%mm0; /* Load y 0x00000000000000yy */ +/* pmullw mpeg3_MMX_601_Y_COEF, %%mm0; // Scale y 0x00000000000000yy */ + psllw $6, %%mm0; /* Shift y coeffs 0x0000yyy0yyy0yyy0 */ + movd %%mm0, (%1); /* Store output */ + " +: +: "r" (&y), "r" (output)); +} + + +int main(int argc, char *argv[]) +{ + unsigned char output[1024]; + + memset(output, 0, 1024); + mpeg3_601_mmx(1, (unsigned long*)output); + printf("%02x%02x\n", *(unsigned char*)&output[1], *(unsigned char*)&output[0]); +} diff --git a/core/multimedia/opieplayer/loopcontrol.cpp b/core/multimedia/opieplayer/loopcontrol.cpp new file mode 100644 index 0000000..93a6e3f --- a/dev/null +++ b/core/multimedia/opieplayer/loopcontrol.cpp @@ -0,0 +1,464 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#ifdef Q_WS_QWS +#include +#endif +#include +#include +#include +#include +#include +#include +#include "loopcontrol.h" +#include "videowidget.h" +#include "audiodevice.h" +#include "mediaplayerplugininterface.h" +#include "mediaplayerstate.h" + + +extern VideoWidget *videoUI; // now only needed to tell it to play a frame +extern MediaPlayerState *mediaPlayerState; + + +//#define DecodeLoopDebug(x) qDebug x +#define DecodeLoopDebug(x) + + +static char *audioBuffer = NULL; +static AudioDevice *audioDevice = NULL; +static bool disabledSuspendScreenSaver = FALSE; +static bool previousSuspendMode = FALSE; + + +pthread_t audio_tid; +pthread_attr_t audio_attr; +bool threadOkToGo = FALSE; + + +class Mutex { +public: + Mutex() { + pthread_mutexattr_t attr; + pthread_mutexattr_init( &attr ); + pthread_mutex_init( &mutex, &attr ); + pthread_mutexattr_destroy( &attr ); + } + + ~Mutex() { + pthread_mutex_destroy( &mutex ); + } + + void lock() { + pthread_mutex_lock( &mutex ); + } + + void unlock() { + pthread_mutex_unlock( &mutex ); + } +private: + pthread_mutex_t mutex; +}; + + +void *startAudioThread( void *ptr ) { + LoopControl *mpegView = (LoopControl *)ptr; + while ( TRUE ) { + if ( threadOkToGo && mpegView->moreAudio ) + mpegView->startAudio(); + else + usleep( 10000 ); // Semi-buzy-wait till we are playing again + } + return 0; +} + + +Mutex *audioMutex; + + +LoopControl::LoopControl( QObject *parent, const char *name ) + : QObject( parent, name ) { + isMuted = FALSE; + connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( setMute(bool) ) ); + + audioMutex = new Mutex; + + pthread_attr_init(&audio_attr); +#define USE_REALTIME_AUDIO_THREAD +#ifdef USE_REALTIME_AUDIO_THREAD + // Attempt to set it to real-time round robin + if ( pthread_attr_setschedpolicy( &audio_attr, SCHED_RR ) == 0 ) { + sched_param params; + params.sched_priority = 50; + pthread_attr_setschedparam(&audio_attr,¶ms); + } else { + qDebug( "Error setting up a realtime thread, reverting to using a normal thread." ); + pthread_attr_destroy(&audio_attr); + pthread_attr_init(&audio_attr); + } +#endif + pthread_create(&audio_tid, &audio_attr, (void * (*)(void *))startAudioThread, this); +} + + +LoopControl::~LoopControl() { + stop(); +} + + +static long prev_frame = 0; +static int currentSample = 0; + + +void LoopControl::timerEvent( QTimerEvent *te ) { + + if ( te->timerId() == videoId ) + startVideo(); + + if ( te->timerId() == sliderId ) { + if ( hasAudioChannel && !hasVideoChannel && moreAudio ) { + mediaPlayerState->updatePosition( audioSampleCounter ); + } else if ( hasVideoChannel && moreVideo ) { + mediaPlayerState->updatePosition( current_frame ); + } + } + + if ( !moreVideo && !moreAudio ) { + mediaPlayerState->setPlaying( FALSE ); + mediaPlayerState->setNext(); + } +} + + +void LoopControl::setPosition( long pos ) { + audioMutex->lock(); + + if ( hasVideoChannel && hasAudioChannel ) { + playtime.restart(); + playtime = playtime.addMSecs( long((double)-pos * 1000.0 / framerate) ); + current_frame = pos + 1; + mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); + prev_frame = current_frame - 1; + currentSample = (int)( (double)current_frame * freq / framerate ); + mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); + audioSampleCounter = currentSample - 1; + } else if ( hasVideoChannel ) { + playtime.restart(); + playtime = playtime.addMSecs( long((double)-pos * 1000.0 / framerate) ); + current_frame = pos + 1; + mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); + prev_frame = current_frame - 1; + } else if ( hasAudioChannel ) { + playtime.restart(); + playtime = playtime.addMSecs( long((double)-pos * 1000.0 / freq) ); + currentSample = pos + 1; + mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); + audioSampleCounter = currentSample - 1; + } + + audioMutex->unlock(); +} + + +void LoopControl::startVideo() { + + if ( moreVideo ) { + + if ( mediaPlayerState->curDecoder() ) { + + if ( hasAudioChannel && !isMuted ) { + + current_frame = long( playtime.elapsed() * framerate / 1000 ); + + if ( prev_frame != -1 && current_frame <= prev_frame ) + return; + + } else { + // Don't skip + current_frame++; + } + + if ( prev_frame == -1 || current_frame > prev_frame ) { + if ( current_frame > prev_frame + 1 ) { + mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); + } + moreVideo = videoUI->playVideo(); + prev_frame = current_frame; + } + + } else { + + moreVideo = FALSE; + killTimer( videoId ); + + } + + } +} + + +void LoopControl::startAudio() { + + audioMutex->lock(); + + if ( moreAudio ) { + + if ( !isMuted && mediaPlayerState->curDecoder() ) { + + currentSample = audioSampleCounter + 1; + + if ( currentSample != audioSampleCounter + 1 ) + qDebug("out of sync with decoder %i %i", currentSample, audioSampleCounter); + + long samplesRead = 0; + mediaPlayerState->curDecoder()->audioReadSamples( (short*)audioBuffer, channels, 1024, samplesRead, stream ); + long sampleWeShouldBeAt = long( playtime.elapsed() ) * freq / 1000; + long sampleWaitTime = currentSample - sampleWeShouldBeAt; + + if ( ( sampleWaitTime > 2000 ) && ( sampleWaitTime < 20000 ) ) { + usleep( (long)((double)sampleWaitTime * 1000000.0 / freq) ); + } else if ( sampleWaitTime <= -5000 ) { + qDebug("need to catch up by: %li (%i,%li)", -sampleWaitTime, currentSample, sampleWeShouldBeAt ); + //mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); + currentSample = sampleWeShouldBeAt; + } + + audioDevice->write( audioBuffer, samplesRead * 2 * channels ); + audioSampleCounter = currentSample + samplesRead - 1; + + moreAudio = audioSampleCounter <= total_audio_samples; + + } else { + + moreAudio = FALSE; + + } + + } + + audioMutex->unlock(); +} + + +void LoopControl::killTimers() { + + audioMutex->lock(); + + if ( hasVideoChannel ) + killTimer( videoId ); + killTimer( sliderId ); + threadOkToGo = FALSE; + + audioMutex->unlock(); +} + + +void LoopControl::startTimers() { + + audioMutex->lock(); + + moreVideo = FALSE; + moreAudio = FALSE; + + if ( hasVideoChannel ) { + moreVideo = TRUE; + int mSecsBetweenFrames = (int)(100 / framerate); // 10% of the real value + videoId = startTimer( mSecsBetweenFrames ); + } + + if ( hasAudioChannel ) { + moreAudio = TRUE; + threadOkToGo = TRUE; + } + + sliderId = startTimer( 300 ); // update slider every 1/3 second + + audioMutex->unlock(); +} + + +void LoopControl::setPaused( bool pause ) { + + if ( !mediaPlayerState->curDecoder() || !mediaPlayerState->curDecoder()->isOpen() ) + return; + + if ( pause ) { + killTimers(); + } else { + // Force an update of the position + mediaPlayerState->setPosition( mediaPlayerState->position() + 1 ); + mediaPlayerState->setPosition( mediaPlayerState->position() - 1 ); + // Just like we never stopped + startTimers(); + } +} + + +void LoopControl::stop( bool willPlayAgainShortly ) { + +#if defined(Q_WS_QWS) && !defined(QT_NO_COP) + if ( !willPlayAgainShortly && disabledSuspendScreenSaver ) { + disabledSuspendScreenSaver = FALSE; + // Re-enable the suspend mode + QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable; + } +#endif + + if ( mediaPlayerState->curDecoder() && mediaPlayerState->curDecoder()->isOpen() ) { + + killTimers(); + + audioMutex->lock(); + + mediaPlayerState->curDecoder()->close(); + + if ( audioDevice ) { + delete audioDevice; + delete audioBuffer; + audioDevice = 0; + audioBuffer = 0; + } + + audioMutex->unlock(); + + } +} + + +bool LoopControl::init( const QString& filename ) { + stop(); + + audioMutex->lock(); + + fileName = filename; + stream = 0; // only play stream 0 for now + current_frame = total_video_frames = total_audio_samples = 0; + + qDebug( "Using the %s decoder", mediaPlayerState->curDecoder()->pluginName() ); + + // ### Hack to use libmpeg3plugin to get the number of audio samples if we are using the libmad plugin + if ( mediaPlayerState->curDecoder()->pluginName() == QString("LibMadPlugin") ) { + if ( mediaPlayerState->libMpeg3Decoder() && mediaPlayerState->libMpeg3Decoder()->open( filename ) ) { + total_audio_samples = mediaPlayerState->libMpeg3Decoder()->audioSamples( 0 ); + mediaPlayerState->libMpeg3Decoder()->close(); + } + } + + if ( !mediaPlayerState->curDecoder()|| !mediaPlayerState->curDecoder()->open( filename ) ) { + audioMutex->unlock(); + return FALSE; + } + + hasAudioChannel = mediaPlayerState->curDecoder()->audioStreams() > 0; + hasVideoChannel = mediaPlayerState->curDecoder()->videoStreams() > 0; + + if ( hasAudioChannel ) { + int astream = 0; + + channels = mediaPlayerState->curDecoder()->audioChannels( astream ); + DecodeLoopDebug(( "channels = %d\n", channels )); + + if ( !total_audio_samples ) + total_audio_samples = mediaPlayerState->curDecoder()->audioSamples( astream ); + + total_audio_samples += 1000; + + mediaPlayerState->setLength( total_audio_samples ); + + freq = mediaPlayerState->curDecoder()->audioFrequency( astream ); + DecodeLoopDebug(( "frequency = %d\n", freq )); + + audioSampleCounter = 0; + + static const int bytes_per_sample = 2; //16 bit + + audioDevice = new AudioDevice( freq, channels, bytes_per_sample ); + audioBuffer = new char[ audioDevice->bufferSize() ]; + channels = audioDevice->channels(); + + //### must check which frequency is actually used. + static const int size = 1; + short int buf[size]; + long samplesRead = 0; + mediaPlayerState->curDecoder()->audioReadSamples( buf, channels, size, samplesRead, stream ); + } + + if ( hasVideoChannel ) { + total_video_frames = mediaPlayerState->curDecoder()->videoFrames( stream ); + + mediaPlayerState->setLength( total_video_frames ); + + framerate = mediaPlayerState->curDecoder()->videoFrameRate( stream ); + DecodeLoopDebug(( "Frame rate %g total %ld", framerate, total_video_frames )); + + if ( framerate <= 1.0 ) { + DecodeLoopDebug(( "Crazy frame rate, resetting to sensible" )); + framerate = 25; + } + + if ( total_video_frames == 1 ) { + DecodeLoopDebug(( "Cannot seek to frame" )); + } + + } + + current_frame = 0; + prev_frame = -1; + + connect( mediaPlayerState, SIGNAL( positionChanged( long ) ), this, SLOT( setPosition( long ) ) ); + connect( mediaPlayerState, SIGNAL( pausedToggled( bool ) ), this, SLOT( setPaused( bool ) ) ); + + audioMutex->unlock(); + + return TRUE; +} + + +void LoopControl::play() { + +#if defined(Q_WS_QWS) && !defined(QT_NO_COP) + if ( !disabledSuspendScreenSaver || previousSuspendMode != hasVideoChannel ) { + disabledSuspendScreenSaver = TRUE; + previousSuspendMode = hasVideoChannel; + // Stop the screen from blanking and power saving state + QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) + << ( hasVideoChannel ? QPEApplication::Disable : QPEApplication::DisableSuspend ); + } +#endif + + playtime.start(); + startTimers(); +} + + +void LoopControl::setMute( bool on ) { + if ( on != isMuted ) { + isMuted = on; + if ( !on ) { + // Force an update of the position + mediaPlayerState->setPosition( mediaPlayerState->position() + 1 ); + mediaPlayerState->setPosition( mediaPlayerState->position() - 1 ); + // Resume playing audio + moreAudio = TRUE; + } + } +} + + diff --git a/core/multimedia/opieplayer/loopcontrol.h b/core/multimedia/opieplayer/loopcontrol.h new file mode 100644 index 0000000..967ee25 --- a/dev/null +++ b/core/multimedia/opieplayer/loopcontrol.h @@ -0,0 +1,88 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEGVIEW_H +#define MPEGVIEW_H + + +#include +#include + + +class LoopControl : public QObject { + Q_OBJECT +public: + LoopControl( QObject *parent, const char *name ); + ~LoopControl(); + + bool init( const QString& filename ); + + bool hasVideo() const { return hasVideoChannel; } + bool hasAudio() const { return hasAudioChannel; } + + long totalPlaytime() { return (long)(hasVideoChannel ? total_video_frames / framerate : total_audio_samples / freq); } + + // These are public to run them from global functions needed to start threads + // Otherwise they would be private + void startAudio(); + void startVideo(); + bool moreAudio; + bool moreVideo; +public slots: + void play(); + void stop( bool willPlayAgainShortly = FALSE ); + + void setMute( bool ); + void setPaused( bool ); + void setPosition( long ); + +signals: + void positionChanged( long, long ); + +protected: + void timerEvent(QTimerEvent*); + +private: + void startTimers(); + void killTimers(); + + QTime playtime; + int videoId; + int sliderId; + + int audioSampleCounter; + long current_frame; + long total_video_frames; + long total_audio_samples; + + float framerate; + int freq; + int stream; + int framecount; + int channels; + + bool hasVideoChannel; + bool hasAudioChannel; + bool isMuted; + QString fileName; +}; + + +#endif + diff --git a/core/multimedia/opieplayer/loopcontrol_threaded.cpp b/core/multimedia/opieplayer/loopcontrol_threaded.cpp new file mode 100644 index 0000000..2ec4a48 --- a/dev/null +++ b/core/multimedia/opieplayer/loopcontrol_threaded.cpp @@ -0,0 +1,626 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#define _REENTRANT + +#include +#include +#include +#ifdef Q_WS_QWS +#include +#endif +#include +#include +#include +#include +#include +#include +#include "loopcontrol.h" +#include "audiodevice.h" +#include "videowidget.h" +#include "audiowidget.h" +#include "mediaplayerplugininterface.h" +#include "mediaplayerstate.h" + + +#if defined(QT_QWS_CUSTOM) || defined(QT_QWS_IPAQ) +#define USE_REALTIME_AUDIO_THREAD +#endif + + +extern VideoWidget *videoUI; // now only needed to tell it to play a frame +extern MediaPlayerState *mediaPlayerState; + + +#define DecodeLoopDebug(x) qDebug x +//#define DecodeLoopDebug(x) + + +static char *audioBuffer = NULL; +static AudioDevice *audioDevice = NULL; +static bool disabledSuspendScreenSaver = FALSE; + + +pthread_t video_tid; +pthread_attr_t video_attr; +pthread_t audio_tid; +pthread_attr_t audio_attr; + + +bool emitPlayFinished = FALSE; +bool emitChangePos = FALSE; + + +class Mutex { +public: + Mutex() { + pthread_mutexattr_t attr; + pthread_mutexattr_init( &attr ); + pthread_mutex_init( &mutex, &attr ); + pthread_mutexattr_destroy( &attr ); + } + + ~Mutex() { + pthread_mutex_destroy( &mutex ); + } + + void lock() { + pthread_mutex_lock( &mutex ); + } + + void unlock() { + pthread_mutex_unlock( &mutex ); + } +/* + bool locked() { + switch ( pthread_mutex_trylock( &mutex ) ) { + case EBUSY: + return TRUE; + case 0: + pthread_mutex_unlock( &mutex ); + default: + return FALSE; + } + } +*/ +private: + pthread_mutex_t mutex; +}; + + +class currentFrameObj { +public: + currentFrameObj() : value( 0 ) { } + void set( long f ) { + mutex.lock(); + value = f; + mediaPlayerState->curDecoder()->videoSetFrame( f, 0 ); + mutex.unlock(); + } + long get() { + return value; + } +private: + long value; + Mutex mutex; +}; + + +Mutex *videoMutex; +Mutex *audioMutex; +Mutex *globalMutex; + + +clock_t begin; + + +LoopControl::LoopControl( QObject *parent, const char *name ) + : QObject( parent, name ) { + isMuted = FALSE; + connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( setMute(bool) ) ); + timerid = startTimer( 200 ); + videoMutex = new Mutex; + audioMutex = new Mutex; + globalMutex = new Mutex; + //begin = clock(); +} + + +LoopControl::~LoopControl() { + stop(); + killTimer( timerid ); +} + + +static bool sendingNewPos = FALSE; +static long prev_frame = 0; +static int currentSample = 0; + + +void LoopControl::timerEvent( QTimerEvent* ) { + // We need to emit playFinished from the main thread, not one of the + // decoding threads else we'll have all kinds of yucky things happen (reentrance). + // playFinished will eventually call stop() which stops these threads. + if ( emitPlayFinished ) { + emitPlayFinished = FALSE; + mediaPlayerState->setPlaying( FALSE ); + } + + if ( emitChangePos ) { + + emitChangePos = FALSE; + + if ( hasVideoChannel && hasAudioChannel ) { + sendingNewPos = TRUE; + mediaPlayerState->setPosition( current_frame ); + } else if ( hasVideoChannel ) { + sendingNewPos = TRUE; + mediaPlayerState->setPosition( current_frame ); + } else if ( hasAudioChannel ) { + sendingNewPos = TRUE; + mediaPlayerState->setPosition( audioSampleCounter ); + } + + } +} + + + + +void LoopControl::setPosition( long pos ) { + if ( sendingNewPos ) { + sendingNewPos = FALSE; + return; + } + + if ( hasVideoChannel && hasAudioChannel ) { + videoMutex->lock(); + audioMutex->lock(); +qDebug("setting position"); + playtime.restart(); + playtime = playtime.addMSecs( -pos * 1000 / framerate ); + //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate; + current_frame = pos + 1; + mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); + prev_frame = current_frame - 1; + currentSample = (int)( current_frame * freq / framerate ); + mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); + audioSampleCounter = currentSample - 1; + audioMutex->unlock(); + videoMutex->unlock(); + } else if ( hasVideoChannel ) { + videoMutex->lock(); + playtime.restart(); + playtime = playtime.addMSecs( -pos * 1000 / framerate ); + //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate; + current_frame = pos + 1; + mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); + videoMutex->unlock(); + prev_frame = current_frame - 1; + } else if ( hasAudioChannel ) { + audioMutex->lock(); + playtime.restart(); + playtime = playtime.addMSecs( -pos * 1000 / freq ); + //begin = clock() - (double)pos * CLOCKS_PER_SEC / freq; + currentSample = pos + 1; // (int)( current_frame * freq / framerate ); + mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); + audioSampleCounter = currentSample - 1; + audioMutex->unlock(); + } +} + + +void *startVideoThread( void *ptr ) { + LoopControl *mpegView = (LoopControl *)ptr; + mpegView->startVideo(); + return 0; +} + +void *startAudioThread( void *ptr ) { + LoopControl *mpegView = (LoopControl *)ptr; + mpegView->startAudio(); + return 0; +} + +void LoopControl::startVideo() { + moreVideo = TRUE; + + while ( moreVideo ) { + + if ( mediaPlayerState->curDecoder() && hasVideoChannel ) { + + if ( hasAudioChannel && !isMuted ) { + + bool done = FALSE; + + do { + + +/* + videoMutex->lock(); + current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); + //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC; + + // Sync to Audio +// current_frame = (long)((double)(audioSampleCounter - 1000) * framerate / (double)freq); + + long mSecsToNextFrame = 0; + + if ( current_frame == prev_frame ) { + int nf = current_frame + 1; + if ( nf > 0 && nf != total_video_frames ) + // mSecsToNextFrame = long(double(nf * CLOCKS_PER_SEC) / framerate) - ( clock() - begin ); + mSecsToNextFrame = long(double(nf * 1000) / framerate) - ( playtime.elapsed() ); + } + videoMutex->unlock(); + + if ( mSecsToNextFrame ) { + usleep( mSecsToNextFrame ); // wait a bit + + videoMutex->lock(); + // This should now be the next frame + current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); + //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC; + videoMutex->unlock(); + } + + videoMutex->lock(); + done = current_frame >= prev_frame; + videoMutex->unlock(); +*/ + videoMutex->lock(); + current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); + done = current_frame >= prev_frame; + videoMutex->unlock(); + if ( !done ) + usleep( 1000 ); // wait a bit + + } while ( !done ); + +// qDebug("elapsed: %i %i (%f)", int( playtime.elapsed() ), current_frame, framerate ); + + } else { + videoMutex->lock(); + current_frame++; + videoMutex->unlock(); + } + + videoMutex->lock(); + bool check = current_frame && current_frame > prev_frame; + videoMutex->unlock(); + + if ( check ) { + videoMutex->lock(); + if ( current_frame > prev_frame + 1 ) { + qDebug("skipped a frame"); + mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); + } + prev_frame = current_frame; + if ( moreVideo = videoUI->playVideo() ) + emitChangePos = TRUE; + videoMutex->unlock(); + } + + } else + moreVideo = FALSE; + + } + + if ( !moreVideo && !moreAudio ) + emitPlayFinished = TRUE; + + pthread_exit(NULL); +} + +void LoopControl::startAudio() { + moreAudio = TRUE; + + while ( moreAudio ) { + + if ( !isMuted && mediaPlayerState->curDecoder() && hasAudioChannel ) { + + audioMutex->lock(); + currentSample = mediaPlayerState->curDecoder()->audioGetSample( stream ); + + if ( currentSample == 0 ) + currentSample = audioSampleCounter + 1; + + if ( currentSample != audioSampleCounter + 1 ) + qDebug("out of sync with decoder %i %i", currentSample, audioSampleCounter); + audioMutex->unlock(); + +/* + int sampleWeShouldBeAt = int( playtime.elapsed() ) * freq / 1000; + + if ( sampleWeShouldBeAt - currentSample > 20000 ) { + mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); + currentSample = sampleWeShouldBeAt; + } +*/ + long samplesRead = 0; + + const long samples = 1024; + + moreAudio = !mediaPlayerState->curDecoder()->audioReadSamples( (short*)audioBuffer, channels, samples, samplesRead, stream ); + + audioMutex->lock(); + long sampleWeShouldBeAt = long( playtime.elapsed() ) * freq / 1000; + //long sampleWeShouldBeAt = long( clock() - begin ) * (double) freq / CLOCKS_PER_SEC; + long sampleWaitTime = currentSample - sampleWeShouldBeAt; + audioMutex->unlock(); + + if ( sampleWaitTime >= 0 && sampleWaitTime <= 2000 ) { + //qDebug("sampleWaitTime: %i", sampleWaitTime); + usleep( ( sampleWaitTime * 1000000 ) / ( freq ) ); + } else { + audioMutex->lock(); + if ( sampleWaitTime <= -2000 ) { + qDebug("need to catch up by: %li (%i,%li)", -sampleWaitTime, currentSample, sampleWeShouldBeAt ); + mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); + currentSample = sampleWeShouldBeAt; + } + audioMutex->unlock(); + } + + audioDevice->write( audioBuffer, samplesRead * 2 * channels ); + + audioMutex->lock(); +// audioSampleCounter += samplesRead; + audioSampleCounter = currentSample + samplesRead - 1; + audioMutex->unlock(); + + if ( !hasVideoChannel ) + emitChangePos = TRUE; + + //qDebug("currentSample: %i audioSampleCounter: %i total_audio_samples: %i", currentSample, audioSampleCounter, total_audio_samples); +// qDebug("current: %i counter: %i total: %i", currentSample, audioSampleCounter, (int)total_audio_samples); + moreAudio = audioSampleCounter <= total_audio_samples; + + } else { + + if ( mediaPlayerState->curDecoder() && hasAudioChannel ) + usleep( 100000 ); // Check every 1/10 sec to see if mute is off + else + moreAudio = FALSE; + + } + } + + qDebug( "End of file" ); + + if ( !moreVideo && !moreAudio ) + emitPlayFinished = TRUE; + + pthread_exit(NULL); +} + +void LoopControl::killTimers() { + if ( hasVideoChannel ) { + if ( pthread_self() != video_tid ) { + if ( pthread_cancel(video_tid) == 0 ) { + void *thread_result = 0; + if ( pthread_join(video_tid,&thread_result) != 0 ) + qDebug("thread join error 1"); + pthread_attr_destroy(&video_attr); + } + } + } + if ( hasAudioChannel ) { + if ( pthread_self() != audio_tid ) { + if ( pthread_cancel(audio_tid) == 0 ) { + void *thread_result = 0; + if ( pthread_join(audio_tid,&thread_result) != 0 ) + qDebug("thread join error 2"); + pthread_attr_destroy(&audio_attr); + } + } + } +} + +void LoopControl::startTimers() { + moreVideo = FALSE; + moreAudio = FALSE; + + if ( hasVideoChannel ) { + moreVideo = TRUE; + pthread_attr_init(&video_attr); + pthread_create(&video_tid, &video_attr, (void * (*)(void *))startVideoThread, this); + } + + if ( hasAudioChannel ) { + moreAudio = TRUE; + pthread_attr_init(&audio_attr); +#ifdef USE_REALTIME_AUDIO_THREAD + pthread_attr_setschedpolicy(&audio_attr,SCHED_RR); // Real-time round robin + //qDebug("min: %i, max: %i", sched_get_priority_min( SCHED_RR ), sched_get_priority_max( SCHED_RR ) ); + sched_param params; + params.sched_priority = 50; + pthread_attr_setschedparam(&audio_attr,¶ms); +#endif + pthread_create(&audio_tid, &audio_attr, (void * (*)(void *))startAudioThread, this); + } +} + + + + +void LoopControl::setPaused( bool pause ) { + static int whenPaused = 0; + + if ( !mediaPlayerState->curDecoder() || !mediaPlayerState->curDecoder()->isOpen() ) + return; + + if ( pause ) { + // Remember where we are + whenPaused = playtime.elapsed(); + killTimers(); + } else { + // Just like we never stopped + playtime.restart(); + playtime = playtime.addMSecs( -whenPaused ); + whenPaused = 0; + startTimers(); + } +} + + +void LoopControl::stop( bool willPlayAgainShortly ) { + +#if defined(Q_WS_QWS) && !defined(QT_NO_COP) + if ( !willPlayAgainShortly && disabledSuspendScreenSaver ) { + disabledSuspendScreenSaver = FALSE; + // Re-enable the suspend mode + QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable; + } +#endif + + if ( mediaPlayerState->curDecoder() && mediaPlayerState->curDecoder()->isOpen() ) { + + killTimers(); + + mediaPlayerState->curDecoder()->close(); + + if ( audioDevice ) { + delete audioDevice; + delete audioBuffer; + audioDevice = 0; + audioBuffer = 0; + } + + } +} + + +bool LoopControl::init( const QString& filename ) { + stop(); + fileName = filename; + stream = 0; // only play stream 0 for now + current_frame = total_video_frames = total_audio_samples = 0; + + qDebug( "Using the %s decoder", mediaPlayerState->curDecoder()->pluginName() ); + + // ### Hack to use libmpeg3plugin to get the number of audio samples if we are using the libmad plugin + if ( mediaPlayerState->curDecoder()->pluginName() == QString("LibMadPlugin") ) { + if ( mediaPlayerState->libMpeg3Decoder() && mediaPlayerState->libMpeg3Decoder()->open( filename ) ) { + total_audio_samples = mediaPlayerState->libMpeg3Decoder()->audioSamples( 0 ); + mediaPlayerState->libMpeg3Decoder()->close(); + } + } + + if ( !mediaPlayerState->curDecoder()|| !mediaPlayerState->curDecoder()->open( filename ) ) + return FALSE; + + hasAudioChannel = mediaPlayerState->curDecoder()->audioStreams() > 0; + hasVideoChannel = mediaPlayerState->curDecoder()->videoStreams() > 0; + + if ( hasAudioChannel ) { + int astream = 0; + + channels = mediaPlayerState->curDecoder()->audioChannels( astream ); + DecodeLoopDebug(( "channels = %d\n", channels )); + + if ( !total_audio_samples ) + total_audio_samples = mediaPlayerState->curDecoder()->audioSamples( astream ); + + mediaPlayerState->setLength( total_audio_samples ); + + freq = mediaPlayerState->curDecoder()->audioFrequency( astream ); + DecodeLoopDebug(( "frequency = %d\n", freq )); + + audioSampleCounter = 0; + + static const int bytes_per_sample = 2; //16 bit + + audioDevice = new AudioDevice( freq, channels, bytes_per_sample ); + audioBuffer = new char[ audioDevice->bufferSize() ]; + channels = audioDevice->channels(); + + //### must check which frequency is actually used. + static const int size = 1; + short int buf[size]; + long samplesRead = 0; + mediaPlayerState->curDecoder()->audioReadSamples( buf, channels, size, samplesRead, stream ); + } + + if ( hasVideoChannel ) { + total_video_frames = mediaPlayerState->curDecoder()->videoFrames( stream ); + + mediaPlayerState->setLength( total_video_frames ); + + framerate = mediaPlayerState->curDecoder()->videoFrameRate( stream ); + DecodeLoopDebug(( "Frame rate %g total %ld", framerate, total_video_frames )); + + if ( framerate <= 1.0 ) { + DecodeLoopDebug(( "Crazy frame rate, resetting to sensible" )); + framerate = 25; + } + + if ( total_video_frames == 1 ) { + DecodeLoopDebug(( "Cannot seek to frame" )); + } + + } + + videoMutex->lock(); + current_frame = 0; + prev_frame = -1; + videoMutex->unlock(); + + connect( mediaPlayerState, SIGNAL( positionChanged( long ) ), this, SLOT( setPosition( long ) ) ); + connect( mediaPlayerState, SIGNAL( pausedToggled( bool ) ), this, SLOT( setPaused( bool ) ) ); + + //setBackgroundColor( black ); + return TRUE; +} + + +void LoopControl::play() { + +#if defined(Q_WS_QWS) && !defined(QT_NO_COP) + if ( !disabledSuspendScreenSaver ) { + disabledSuspendScreenSaver = TRUE; + // Stop the screen from blanking and power saving state + QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) + << ( hasVideoChannel ? QPEApplication::Disable : QPEApplication::DisableSuspend ); + } +#endif + + //begin = clock(); + playtime.start(); + startTimers(); + //updateGeometry(); +} + + +void LoopControl::setMute( bool on ) { + if ( isMuted != on ) { + isMuted = on; + if ( isMuted ) { + } else { + int frame = current_frame; // mediaPlayerState->curDecoder()->videoGetFrame( stream ); + playtime.restart(); + playtime = playtime.addMSecs( -frame * 1000 / framerate ); + //begin = clock() - (double)frame * CLOCKS_PER_SEC / framerate; + mediaPlayerState->curDecoder()->audioSetSample( frame*freq/framerate, stream ); + } + } +} + + diff --git a/core/multimedia/opieplayer/loopcontrol_threaded.h b/core/multimedia/opieplayer/loopcontrol_threaded.h new file mode 100644 index 0000000..9a009d1 --- a/dev/null +++ b/core/multimedia/opieplayer/loopcontrol_threaded.h @@ -0,0 +1,89 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEGVIEW_H +#define MPEGVIEW_H + + +#include +#include + + +class LoopControl : public QObject { + Q_OBJECT +public: + LoopControl( QObject *parent, const char *name ); + ~LoopControl(); + + bool init( const QString& filename ); + + bool hasVideo() const { return hasVideoChannel; } + bool hasAudio() const { return hasAudioChannel; } + + long totalPlaytime() { return (long)(hasVideoChannel ? total_video_frames / framerate : total_audio_samples / freq); } + + // These are public to run them from global functions needed to start threads + // Otherwise they would be private + void startAudio(); + void startVideo(); +public slots: + void play(); + void stop( bool willPlayAgainShortly = FALSE ); + + void setMute( bool ); + void setPaused( bool ); + void setPosition( long ); + +signals: + void positionChanged( long, long ); + void playFinished(); + +protected: + void timerEvent(QTimerEvent*); + +private: + void startTimers(); + void killTimers(); + + + QTime playtime; + int timerid; + int audioSampleCounter; + long current_frame; + long total_video_frames; + long total_audio_samples; + + float framerate; + int freq; + int stream; + int framecount; + int channels; + + bool moreAudio; + bool moreVideo; + + bool hasVideoChannel; + bool hasAudioChannel; + bool isMuted; + QString fileName; +}; + + +#endif + diff --git a/core/multimedia/opieplayer/main.cpp b/core/multimedia/opieplayer/main.cpp new file mode 100644 index 0000000..5246e40 --- a/dev/null +++ b/core/multimedia/opieplayer/main.cpp @@ -0,0 +1,57 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#include "mediaplayerstate.h" +#include "playlistwidget.h" +#include "audiowidget.h" +#include "videowidget.h" +#include "loopcontrol.h" +#include "mediaplayer.h" + + +MediaPlayerState *mediaPlayerState; +PlayListWidget *playList; +AudioWidget *audioUI; +VideoWidget *videoUI; +LoopControl *loopControl; + + +int main(int argc, char **argv) { + QPEApplication a(argc,argv); + + MediaPlayerState st( 0, "mediaPlayerState" ); + mediaPlayerState = &st; + PlayListWidget pl( 0, "playList" ); + playList = &pl; + AudioWidget aw( 0, "audioUI" ); + audioUI = &aw; + VideoWidget vw( 0, "videoUI" ); + videoUI = &vw; + LoopControl lc( 0, "loopControl" ); + loopControl = &lc; + MediaPlayer mp( 0, "mediaPlayer" ); + + pl.setCaption( MediaPlayer::tr("Media Player") ); + a.showMainDocumentWidget(&pl); + + return a.exec(); +} + + diff --git a/core/multimedia/opieplayer/mediaplayer.cpp b/core/multimedia/opieplayer/mediaplayer.cpp new file mode 100644 index 0000000..3d8f76c --- a/dev/null +++ b/core/multimedia/opieplayer/mediaplayer.cpp @@ -0,0 +1,182 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mediaplayer.h" +#include "playlistwidget.h" +#include "audiowidget.h" +#include "loopcontrol.h" +#include "audiodevice.h" + +#include "mediaplayerstate.h" + + +extern AudioWidget *audioUI; +extern PlayListWidget *playList; +extern LoopControl *loopControl; +extern MediaPlayerState *mediaPlayerState; + + +MediaPlayer::MediaPlayer( QObject *parent, const char *name ) + : QObject( parent, name ), volumeDirection( 0 ), currentFile( NULL ) { + + connect( mediaPlayerState, SIGNAL( playingToggled( bool ) ), this, SLOT( setPlaying( bool ) ) ); + connect( mediaPlayerState, SIGNAL( pausedToggled( bool ) ), this, SLOT( pauseCheck( bool ) ) ); + connect( mediaPlayerState, SIGNAL( next() ), this, SLOT( next() ) ); + connect( mediaPlayerState, SIGNAL( prev() ), this, SLOT( prev() ) ); + + connect( audioUI, SIGNAL( moreClicked() ), this, SLOT( startIncreasingVolume() ) ); + connect( audioUI, SIGNAL( lessClicked() ), this, SLOT( startDecreasingVolume() ) ); + connect( audioUI, SIGNAL( moreReleased() ), this, SLOT( stopChangingVolume() ) ); + connect( audioUI, SIGNAL( lessReleased() ), this, SLOT( stopChangingVolume() ) ); +} + + +MediaPlayer::~MediaPlayer() { +} + + +void MediaPlayer::pauseCheck( bool b ) { + // Only pause if playing + if ( b && !mediaPlayerState->playing() ) + mediaPlayerState->setPaused( FALSE ); +} + + +void MediaPlayer::play() { + mediaPlayerState->setPlaying( FALSE ); + mediaPlayerState->setPlaying( TRUE ); +} + + +void MediaPlayer::setPlaying( bool play ) { + + if ( !play ) { + mediaPlayerState->setPaused( FALSE ); + loopControl->stop( FALSE ); + return; + } + + if ( mediaPlayerState->paused() ) { + mediaPlayerState->setPaused( FALSE ); + return; + } + + const DocLnk *playListCurrent = playList->current(); + + if ( playListCurrent != NULL ) { + loopControl->stop( TRUE ); + currentFile = playListCurrent; + } + + if ( currentFile == NULL ) { + QMessageBox::critical( 0, tr( "No file"), tr( "Error: There is no file selected" ) ); + mediaPlayerState->setPlaying( FALSE ); + return; + } + + if ( !QFile::exists( currentFile->file() ) ) { + QMessageBox::critical( 0, tr( "File not found"), tr( "The following file was not found: " ) + currentFile->file() + "" ); + mediaPlayerState->setPlaying( FALSE ); + return; + } + + if ( !mediaPlayerState->newDecoder( currentFile->file() ) ) { + QMessageBox::critical( 0, tr( "No decoder found"), tr( "Sorry, no appropriate decoders found for this file: " ) + currentFile->file() + "" ); + mediaPlayerState->setPlaying( FALSE ); + return; + } + + if ( !loopControl->init( currentFile->file() ) ) { + QMessageBox::critical( 0, tr( "Error opening file"), tr( "Sorry, an error occured trying to play the file: " ) + currentFile->file() + "" ); + mediaPlayerState->setPlaying( FALSE ); + return; + } + + long seconds = loopControl->totalPlaytime(); + QString time; time.sprintf("%li:%02i", seconds/60, (int)seconds%60 ); + QString tickerText = tr( " File: " ) + currentFile->name() + tr(", Length: ") + time; + QString fileInfo = mediaPlayerState->curDecoder()->fileInfo(); + if ( !fileInfo.isEmpty() ) + tickerText += ", " + fileInfo; + audioUI->setTickerText( tickerText + "." ); + + loopControl->play(); + + mediaPlayerState->setView( loopControl->hasVideo() ? 'v' : 'a' ); +} + + +void MediaPlayer::prev() { + if ( playList->prev() ) + play(); + else if ( mediaPlayerState->looping() ) { + if ( playList->last() ) + play(); + } else + mediaPlayerState->setList(); +} + + +void MediaPlayer::next() { + if ( playList->next() ) + play(); + else if ( mediaPlayerState->looping() ) { + if ( playList->first() ) + play(); + } else + mediaPlayerState->setList(); +} + + +void MediaPlayer::startDecreasingVolume() { + volumeDirection = -1; + startTimer( 100 ); + AudioDevice::decreaseVolume(); +} + + +void MediaPlayer::startIncreasingVolume() { + volumeDirection = +1; + startTimer( 100 ); + AudioDevice::increaseVolume(); +} + + +void MediaPlayer::stopChangingVolume() { + killTimers(); +} + + +void MediaPlayer::timerEvent( QTimerEvent * ) { + if ( volumeDirection == +1 ) + AudioDevice::increaseVolume(); + else if ( volumeDirection == -1 ) + AudioDevice::decreaseVolume(); +} + diff --git a/core/multimedia/opieplayer/mediaplayer.h b/core/multimedia/opieplayer/mediaplayer.h new file mode 100644 index 0000000..379d95c --- a/dev/null +++ b/core/multimedia/opieplayer/mediaplayer.h @@ -0,0 +1,59 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MEDIA_PLAYER_H +#define MEDIA_PLAYER_H + + +#include +#include +#include +#include "mediaplayerplugininterface.h" + + +class DocLnk; + + +class MediaPlayer : public QObject { + Q_OBJECT +public: + MediaPlayer( QObject *parent, const char *name ); + ~MediaPlayer(); + +private slots: + void setPlaying( bool ); + void pauseCheck( bool ); + void play(); + void next(); + void prev(); + void startIncreasingVolume(); + void startDecreasingVolume(); + void stopChangingVolume(); + +protected: + void timerEvent( QTimerEvent *e ); + +private: + int volumeDirection; + const DocLnk *currentFile; +}; + + +#endif // MEDIA_PLAYER_H + diff --git a/core/multimedia/opieplayer/mediaplayerplugininterface.h b/core/multimedia/opieplayer/mediaplayerplugininterface.h new file mode 100644 index 0000000..24d5a80 --- a/dev/null +++ b/core/multimedia/opieplayer/mediaplayerplugininterface.h @@ -0,0 +1,113 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MEDIA_PLAYER_PLUGIN_INTERFACE_H +#define MEDIA_PLAYER_PLUGIN_INTERFACE_H + +#include + +#ifndef QT_NO_COMPONENT +// {c0093632-b44c-4cf7-a279-d82fe8a8890c} +# ifndef IID_MediaPlayerPlugin +# define IID_MediaPlayerPlugin QUuid( 0xc0093632, 0xb44c, 0x4cf7, 0xa2, 0x79, 0xd8, 0x2f, 0xe8, 0xa8, 0x89, 0x0c ) +# endif +#endif + + +enum ColorFormat { + RGB565, + BGR565, + RGBA8888, + BGRA8888 +}; + + +class MediaPlayerDecoder { + +public: + virtual ~MediaPlayerDecoder() { }; + + // About Plugin + virtual const char *pluginName() = 0; + virtual const char *pluginComment() = 0; + virtual double pluginVersion() = 0; + + virtual bool isFileSupported( const QString& file ) = 0; + virtual bool open( const QString& file ) = 0; + virtual bool close() = 0; + virtual bool isOpen() = 0; + virtual const QString &fileInfo() = 0; + + // If decoder doesn't support audio then return 0 here + virtual int audioStreams() = 0; + virtual int audioChannels( int stream ) = 0; + virtual int audioFrequency( int stream ) = 0; + virtual int audioSamples( int stream ) = 0; + virtual bool audioSetSample( long sample, int stream ) = 0; + virtual long audioGetSample( int stream ) = 0; +// virtual bool audioReadMonoSamples( short *samples, long samples, long& samplesRead, int stream ) = 0; +// virtual bool audioReadStereoSamples( short *samples, long samples, long& samplesRead, int stream ) = 0; + virtual bool audioReadSamples( short *samples, int channels, long samples, long& samplesRead, int stream ) = 0; + // Libmpeg3 functions, perhaps good for reading an audio file with 5 channels or something! +// virtual bool audioReadSamples( short *samples, int channel, long samples, int stream ) = 0; +// virtual bool audioReReadSamples( short *samples, int channel, long samples, int stream ) = 0; + + // If decoder doesn't support video then return 0 here + virtual int videoStreams() = 0; + virtual int videoWidth( int stream ) = 0; + virtual int videoHeight( int stream ) = 0; + virtual double videoFrameRate( int stream ) = 0; // frames per second (this may change to frames/1000secs) + virtual int videoFrames( int stream ) = 0; + virtual bool videoSetFrame( long sample, int stream ) = 0; + virtual long videoGetFrame( int stream ) = 0; + virtual bool videoReadFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, ColorFormat color_model, int stream ) = 0; + virtual bool videoReadScaledFrame( unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, ColorFormat color_model, int stream ) = 0; + virtual bool videoReadYUVFrame( char *y_output, char *u_output, char *v_output, int in_x, int in_y, int in_w, int in_h, int stream ) = 0; + + // Profiling + virtual double getTime() = 0; + + // Ignore if these aren't supported + virtual bool setSMP( int cpus ) = 0; + virtual bool setMMX( bool useMMX ) = 0; + + // Capabilities + virtual bool supportsAudio() = 0; + virtual bool supportsVideo() = 0; + virtual bool supportsYUV() = 0; + virtual bool supportsMMX() = 0; + virtual bool supportsSMP() = 0; + virtual bool supportsStereo() = 0; + virtual bool supportsScaling() = 0; + +}; + + +class MediaPlayerEncoder; + + +struct MediaPlayerPluginInterface : public QUnknownInterface +{ + virtual MediaPlayerDecoder *decoder() = 0; + virtual MediaPlayerEncoder *encoder() = 0; +}; + + +#endif + diff --git a/core/multimedia/opieplayer/mediaplayerstate.cpp b/core/multimedia/opieplayer/mediaplayerstate.cpp new file mode 100644 index 0000000..9b9d133 --- a/dev/null +++ b/core/multimedia/opieplayer/mediaplayerstate.cpp @@ -0,0 +1,185 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#include +#include +#include +#include +#include +#include "mediaplayerplugininterface.h" +#include "mediaplayerstate.h" + +#ifdef QT_NO_COMPONENT +// Plugins which are compiled in when no plugin architecture available +#include "libmad/libmadpluginimpl.h" +#include "libmpeg3/libmpeg3pluginimpl.h" +#include "wavplugin/wavpluginimpl.h" +#endif + + +//#define MediaPlayerDebug(x) qDebug x +#define MediaPlayerDebug(x) + + +MediaPlayerState::MediaPlayerState( QObject *parent, const char *name ) + : QObject( parent, name ), decoder( NULL ), libmpeg3decoder( NULL ) { + Config cfg( "MediaPlayer" ); + readConfig( cfg ); + loadPlugins(); +} + + +MediaPlayerState::~MediaPlayerState() { + Config cfg( "MediaPlayer" ); + writeConfig( cfg ); +} + + +void MediaPlayerState::readConfig( Config& cfg ) { + cfg.setGroup("Options"); + isFullscreen = cfg.readBoolEntry( "FullScreen" ); + isScaled = cfg.readBoolEntry( "Scaling" ); + isLooping = cfg.readBoolEntry( "Looping" ); + isShuffled = cfg.readBoolEntry( "Shuffle" ); + usePlaylist = cfg.readBoolEntry( "UsePlayList" ); + isPlaying = FALSE; + isPaused = FALSE; + curPosition = 0; + curLength = 0; + curView = 'l'; +} + + +void MediaPlayerState::writeConfig( Config& cfg ) const { + cfg.setGroup("Options"); + cfg.writeEntry("FullScreen", isFullscreen ); + cfg.writeEntry("Scaling", isScaled ); + cfg.writeEntry("Looping", isLooping ); + cfg.writeEntry("Shuffle", isShuffled ); + cfg.writeEntry("UsePlayList", usePlaylist ); +} + + +struct MediaPlayerPlugin { +#ifndef QT_NO_COMPONENT + QLibrary *library; +#endif + MediaPlayerPluginInterface *iface; + MediaPlayerDecoder *decoder; + MediaPlayerEncoder *encoder; +}; + + +static QValueList pluginList; + + +// Find the first decoder which supports this type of file +MediaPlayerDecoder *MediaPlayerState::newDecoder( const QString& file ) { + MediaPlayerDecoder *tmpDecoder = NULL; + QValueList::Iterator it; + for ( it = pluginList.begin(); it != pluginList.end(); ++it ) { + if ( (*it).decoder->isFileSupported( file ) ) { + tmpDecoder = (*it).decoder; + break; + } + } + return decoder = tmpDecoder; +} + + +MediaPlayerDecoder *MediaPlayerState::curDecoder() { + return decoder; +} + + +// ### hack to get true sample count +MediaPlayerDecoder *MediaPlayerState::libMpeg3Decoder() { + return libmpeg3decoder; +} + + +void MediaPlayerState::loadPlugins() { + +#ifndef QT_NO_COMPONENT + QValueList::Iterator mit; + for ( mit = pluginList.begin(); mit != pluginList.end(); ++mit ) { + (*mit).iface->release(); + (*mit).library->unload(); + delete (*mit).library; + } + pluginList.clear(); + + QString path = QPEApplication::qpeDir() + "/plugins/codecs"; + QDir dir( path, "lib*.so" ); + QStringList list = dir.entryList(); + QStringList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + MediaPlayerPluginInterface *iface = 0; + QLibrary *lib = new QLibrary( path + "/" + *it ); + + MediaPlayerDebug(( "querying: %s", QString( path + "/" + *it ).latin1() )); + + if ( lib->queryInterface( IID_MediaPlayerPlugin, (QUnknownInterface**)&iface ) == QS_OK ) { + + MediaPlayerDebug(( "loading: %s", QString( path + "/" + *it ).latin1() )); + + MediaPlayerPlugin plugin; + plugin.library = lib; + plugin.iface = iface; + plugin.decoder = plugin.iface->decoder(); + plugin.encoder = plugin.iface->encoder(); + pluginList.append( plugin ); + + // ### hack to get true sample count + if ( plugin.decoder->pluginName() == QString("LibMpeg3Plugin") ) + libmpeg3decoder = plugin.decoder; + + } else { + delete lib; + } + } +#else + pluginList.clear(); + + MediaPlayerPlugin plugin0; + plugin0.iface = new LibMpeg3PluginImpl; + plugin0.decoder = plugin0.iface->decoder(); + plugin0.encoder = plugin0.iface->encoder(); + pluginList.append( plugin0 ); + + MediaPlayerPlugin plugin1; + plugin1.iface = new LibMadPluginImpl; + plugin1.decoder = plugin1.iface->decoder(); + plugin1.encoder = plugin1.iface->encoder(); + pluginList.append( plugin1 ); + + MediaPlayerPlugin plugin2; + plugin2.iface = new WavPluginImpl; + plugin2.decoder = plugin2.iface->decoder(); + plugin2.encoder = plugin2.iface->encoder(); + pluginList.append( plugin2 ); +#endif + + if ( pluginList.count() ) + MediaPlayerDebug(( "%i decoders found", pluginList.count() )); + else + MediaPlayerDebug(( "No decoders found" )); +} + diff --git a/core/multimedia/opieplayer/mediaplayerstate.h b/core/multimedia/opieplayer/mediaplayerstate.h new file mode 100644 index 0000000..5d95b92 --- a/dev/null +++ b/core/multimedia/opieplayer/mediaplayerstate.h @@ -0,0 +1,117 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MEDIA_PLAYER_STATE_H +#define MEDIA_PLAYER_STATE_H + + +#include + + +class MediaPlayerDecoder; +class Config; + + +class MediaPlayerState : public QObject { +Q_OBJECT +public: + MediaPlayerState( QObject *parent, const char *name ); + ~MediaPlayerState(); + + bool fullscreen() { return isFullscreen; } + bool scaled() { return isScaled; } + bool looping() { return isLooping; } + bool shuffled() { return isShuffled; } + bool playlist() { return usePlaylist; } + bool paused() { return isPaused; } + bool playing() { return isPlaying; } + long position() { return curPosition; } + long length() { return curLength; } + char view() { return curView; } + + MediaPlayerDecoder *newDecoder( const QString& file ); + MediaPlayerDecoder *curDecoder(); + MediaPlayerDecoder *libMpeg3Decoder(); // ### Yucky hack needed to use libmpeg3plugin to get the + // number of audio samples if we are using the libmad plugin +public slots: + void setFullscreen( bool b ) { if ( isFullscreen == b ) return; isFullscreen = b; emit fullscreenToggled(b); } + void setScaled( bool b ) { if ( isScaled == b ) return; isScaled = b; emit scaledToggled(b); } + void setLooping( bool b ) { if ( isLooping == b ) return; isLooping = b; emit loopingToggled(b); } + void setShuffled( bool b ) { if ( isShuffled == b ) return; isShuffled = b; emit shuffledToggled(b); } + void setPlaylist( bool b ) { if ( usePlaylist == b ) return; usePlaylist = b; emit playlistToggled(b); } + void setPaused( bool b ) { if ( isPaused == b ) return; isPaused = b; emit pausedToggled(b); } + void setPlaying( bool b ) { if ( isPlaying == b ) return; isPlaying = b; emit playingToggled(b); } + void setPosition( long p ) { if ( curPosition == p ) return; curPosition = p; emit positionChanged(p); } + void updatePosition( long p ){ if ( curPosition == p ) return; curPosition = p; emit positionUpdated(p); } + void setLength( long l ) { if ( curLength == l ) return; curLength = l; emit lengthChanged(l); } + void setView( char v ) { if ( curView == v ) return; curView = v; emit viewChanged(v); } + + void setPrev() { emit prev(); } + void setNext() { emit next(); } + void setList() { setPlaying( FALSE ); setView('l'); } + void setVideo() { setView('v'); } + void setAudio() { setView('a'); } + + void toggleFullscreen() { setFullscreen( !isFullscreen ); } + void toggleScaled() { setScaled( !isScaled); } + void toggleLooping() { setLooping( !isLooping); } + void toggleShuffled() { setShuffled( !isShuffled); } + void togglePlaylist() { setPlaylist( !usePlaylist); } + void togglePaused() { setPaused( !isPaused); } + void togglePlaying() { setPlaying( !isPlaying); } + +signals: + void fullscreenToggled( bool ); + void scaledToggled( bool ); + void loopingToggled( bool ); + void shuffledToggled( bool ); + void playlistToggled( bool ); + void pausedToggled( bool ); + void playingToggled( bool ); + void positionChanged( long ); // When the slider is moved + void positionUpdated( long ); // When the media file progresses + void lengthChanged( long ); + void viewChanged( char ); + + void prev(); + void next(); + +private: + bool isFullscreen; + bool isScaled; + bool isLooping; + bool isShuffled; + bool usePlaylist; + bool isPaused; + bool isPlaying; + long curPosition; + long curLength; + char curView; + + MediaPlayerDecoder *decoder; + MediaPlayerDecoder *libmpeg3decoder; + + void loadPlugins(); + void readConfig( Config& cfg ); + void writeConfig( Config& cfg ) const; +}; + + +#endif // MEDIA_PLAYER_STATE_H + diff --git a/core/multimedia/opieplayer/mpegplayer.pro b/core/multimedia/opieplayer/mpegplayer.pro new file mode 100644 index 0000000..d6952f8 --- a/dev/null +++ b/core/multimedia/opieplayer/mpegplayer.pro @@ -0,0 +1,21 @@ +TEMPLATE = app +CONFIG = qt warn_on release +DESTDIR = $(QPEDIR)/bin +HEADERS = loopcontrol.h mediaplayerplugininterface.h playlistselection.h mediaplayerstate.h \ + videowidget.h audiowidget.h playlistwidget.h mediaplayer.h audiodevice.h +SOURCES = main.cpp \ + loopcontrol.cpp playlistselection.cpp mediaplayerstate.cpp \ + videowidget.cpp audiowidget.cpp playlistwidget.cpp mediaplayer.cpp audiodevice.cpp +TARGET = mpegplayer +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe -lpthread + +# INTERFACES = +# INCLUDEPATH += $(QPEDIR)/include +# CONFIG+=static +# TMAKE_CXXFLAGS += -DQPIM_STANDALONE +# LIBS += libmpeg3/libmpeg3.a -lpthread +# LIBS += $(QPEDIR)/plugins/codecs/liblibmadplugin.so + +TRANSLATIONS = ../i18n/de/mpegplayer.ts diff --git a/core/multimedia/opieplayer/playlistselection.cpp b/core/multimedia/opieplayer/playlistselection.cpp new file mode 100644 index 0000000..fbfb946 --- a/dev/null +++ b/core/multimedia/opieplayer/playlistselection.cpp @@ -0,0 +1,179 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "playlistselection.h" + +#include + + +class PlayListSelectionItem : public QListViewItem { +public: + PlayListSelectionItem( QListView *parent, const DocLnk *f ) : QListViewItem( parent ), fl( f ) { + setText( 0, f->name() ); + setPixmap( 0, f->pixmap() ); + } + + ~PlayListSelectionItem() { + }; + + const DocLnk *file() const { return fl; } + +private: + const DocLnk *fl; +}; + + +PlayListSelection::PlayListSelection( QWidget *parent, const char *name ) + : QListView( parent, name ) +{ +#ifdef USE_PLAYLIST_BACKGROUND + setStaticBackground( TRUE ); + setBackgroundPixmap( Resource::loadPixmap( "mpegplayer/background" ) ); +#endif + setAllColumnsShowFocus( TRUE ); + addColumn( tr( "Playlist Selection" ) ); + header()->hide(); + setSorting( -1, FALSE ); +} + + +PlayListSelection::~PlayListSelection() { +} + + +#ifdef USE_PLAYLIST_BACKGROUND +void PlayListSelection::drawBackground( QPainter *p, const QRect &r ) { + p->fillRect( r, QBrush( white ) ); + QImage logo = Resource::loadImage( "mpegplayer/background" ); + if ( !logo.isNull() ) + p->drawImage( (width() - logo.width()) / 2, (height() - logo.height()) / 2, logo ); +} +#endif + + +void PlayListSelection::contentsMouseMoveEvent( QMouseEvent *event ) { + if ( event->state() == QMouseEvent::LeftButton ) { + QListViewItem *currentItem = selectedItem(); + QListViewItem *itemUnder = itemAt( QPoint( event->pos().x(), event->pos().y() - contentsY() ) ); + if ( currentItem && currentItem->itemAbove() == itemUnder ) + moveSelectedUp(); + else if ( currentItem && currentItem->itemBelow() == itemUnder ) + moveSelectedDown(); + } +} + + +const DocLnk *PlayListSelection::current() { + PlayListSelectionItem *item = (PlayListSelectionItem *)selectedItem(); + if ( item ) + return item->file(); + return NULL; +} + + +void PlayListSelection::addToSelection( const DocLnk &lnk ) { + PlayListSelectionItem *item = new PlayListSelectionItem( this, new DocLnk( lnk ) ); + QListViewItem *current = selectedItem(); + if ( current ) + item->moveItem( current ); + setSelected( item, TRUE ); + ensureItemVisible( selectedItem() ); +} + + +void PlayListSelection::removeSelected() { + QListViewItem *item = selectedItem(); + if ( item ) + delete item; + setSelected( currentItem(), TRUE ); + ensureItemVisible( selectedItem() ); +} + + +void PlayListSelection::moveSelectedUp() { + QListViewItem *item = selectedItem(); + if ( item && item->itemAbove() ) + item->itemAbove()->moveItem( item ); + ensureItemVisible( selectedItem() ); +} + + +void PlayListSelection::moveSelectedDown() { + QListViewItem *item = selectedItem(); + if ( item && item->itemBelow() ) + item->moveItem( item->itemBelow() ); + ensureItemVisible( selectedItem() ); +} + + +bool PlayListSelection::prev() { + QListViewItem *item = selectedItem(); + if ( item && item->itemAbove() ) + setSelected( item->itemAbove(), TRUE ); + else + return FALSE; + ensureItemVisible( selectedItem() ); + return TRUE; +} + + +bool PlayListSelection::next() { + QListViewItem *item = selectedItem(); + if ( item && item->itemBelow() ) + setSelected( item->itemBelow(), TRUE ); + else + return FALSE; + ensureItemVisible( selectedItem() ); + return TRUE; +} + + +bool PlayListSelection::first() { + QListViewItem *item = firstChild(); + if ( item ) + setSelected( item, TRUE ); + else + return FALSE; + ensureItemVisible( selectedItem() ); + return TRUE; +} + + +bool PlayListSelection::last() { + QListViewItem *prevItem = NULL; + QListViewItem *item = firstChild(); + while ( ( item = item->nextSibling() ) ) + prevItem = item; + if ( prevItem ) + setSelected( prevItem, TRUE ); + else + return FALSE; + ensureItemVisible( selectedItem() ); + return TRUE; +} + diff --git a/core/multimedia/opieplayer/playlistselection.h b/core/multimedia/opieplayer/playlistselection.h new file mode 100644 index 0000000..6ce6bdc --- a/dev/null +++ b/core/multimedia/opieplayer/playlistselection.h @@ -0,0 +1,62 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef PLAY_LIST_SELECTION_H +#define PLAY_LIST_SELECTION_H + + +#include +#include +#include + + +class PlayListSelection : public QListView { + Q_OBJECT +public: + PlayListSelection( QWidget *parent, const char *name=0 ); + ~PlayListSelection(); + + const DocLnk *current(); // retrieve the current playlist entry (media file link) + +public slots: + void addToSelection( const DocLnk & ); // Add a media file to the playlist + void removeSelected(); // Remove a media file from the playlist + void moveSelectedUp(); // Move the media file up the playlist so it is played earlier + void moveSelectedDown(); // Move the media file down the playlist so it is played later + bool prev(); + bool next(); + bool first(); + bool last(); + +protected: + virtual void contentsMouseMoveEvent(QMouseEvent *); +#ifdef USE_PLAYLIST_BACKGROUND + virtual void drawBackground( QPainter *p, const QRect &r ); + virtual void paintEmptyArea( QPainter *p, const QRect &r ) { drawBackground( p, r ); }; +#endif + +private: + QList selectedList; + const DocLnk *lnk; +}; + + +#endif // PLAY_LIST_SELECTION_H + + diff --git a/core/multimedia/opieplayer/playlistwidget.cpp b/core/multimedia/opieplayer/playlistwidget.cpp new file mode 100644 index 0000000..969fc4b --- a/dev/null +++ b/core/multimedia/opieplayer/playlistwidget.cpp @@ -0,0 +1,448 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "playlistselection.h" +#include "playlistwidget.h" +#include "mediaplayerstate.h" + +#include + + +extern MediaPlayerState *mediaPlayerState; + + +class PlayListWidgetPrivate { +public: + QToolButton *tbPlay; + QToolButton *tbFull; + QToolButton *tbLoop; + QToolButton *tbScale; + QToolButton *tbShuffle; + + QFrame *playListFrame; + FileSelector *files; + PlayListSelection *selectedFiles; + bool setDocumentUsed; + DocLnk *current; +}; + + +class ToolButton : public QToolButton { +public: + ToolButton( QWidget *parent, const char *name, const QString& icon, QObject *handler, const QString& slot, bool t = FALSE ) + : QToolButton( parent, name ) { + setTextLabel( name ); + setPixmap( Resource::loadPixmap( icon ) ); + setAutoRaise( TRUE ); + setFocusPolicy( QWidget::NoFocus ); + setToggleButton( t ); + connect( this, t ? SIGNAL( toggled(bool) ) : SIGNAL( clicked() ), handler, slot ); + QPEMenuToolFocusManager::manager()->addWidget( this ); + } +}; + + +class MenuItem : public QAction { +public: + MenuItem( QWidget *parent, const QString& text, QObject *handler, const QString& slot ) + : QAction( text, QString::null, 0, 0 ) { + connect( this, SIGNAL( activated() ), handler, slot ); + addTo( parent ); + } +}; + + +PlayListWidget::PlayListWidget( QWidget* parent, const char* name, WFlags fl ) + : QMainWindow( parent, name, fl ) { + + d = new PlayListWidgetPrivate; + d->setDocumentUsed = FALSE; + d->current = NULL; + + setBackgroundMode( PaletteButton ); + + setCaption( tr("MediaPlayer") ); + setIcon( Resource::loadPixmap( "MPEGPlayer" ) ); + + setToolBarsMovable( FALSE ); + + // Create Toolbar + QPEToolBar *toolbar = new QPEToolBar( this ); + toolbar->setHorizontalStretchable( TRUE ); + + // Create Menubar + QPEMenuBar *menu = new QPEMenuBar( toolbar ); + menu->setMargin( 0 ); + + QPEToolBar *bar = new QPEToolBar( this ); + bar->setLabel( tr( "Play Operations" ) ); +#ifdef BUTTONS_ON_TOOLBAR + d->tbPlay = new ToolButton( bar, tr( "Play" ), "mpegplayer/play", mediaPlayerState, SLOT(setPlaying(bool)), TRUE ); + d->tbShuffle = new ToolButton( bar, tr( "Randomize" ), "mpegplayer/shuffle", mediaPlayerState, SLOT(setShuffled(bool)), TRUE ); +#endif + d->tbLoop = new ToolButton( bar, tr( "Loop" ), "mpegplayer/loop", mediaPlayerState, SLOT(setLooping(bool)), TRUE ); + d->tbFull = new ToolButton( bar, tr( "Fullscreen" ), "fullscreen", mediaPlayerState, SLOT(setFullscreen(bool)), TRUE ); + d->tbScale = new ToolButton( bar, tr( "Scale" ), "mpegplayer/scale", mediaPlayerState, SLOT(setScaled(bool)), TRUE ); + + QPopupMenu *pmPlayList = new QPopupMenu( this ); + menu->insertItem( tr( "PlayList" ), pmPlayList ); + new MenuItem( pmPlayList, tr( "Toggle PlayList" ), mediaPlayerState, SLOT( togglePlaylist() ) ); + new MenuItem( pmPlayList, tr( "Clear List" ), this, SLOT( clearList() ) ); + new MenuItem( pmPlayList, tr( "Add all music files" ), this, SLOT( addAllMusicToList() ) ); + new MenuItem( pmPlayList, tr( "Add all video files" ), this, SLOT( addAllVideoToList() ) ); + new MenuItem( pmPlayList, tr( "Add all files" ), this, SLOT( addAllToList() ) ); +#ifdef CAN_SAVE_LOAD_PLAYLISTS + new MenuItem( pmPlayList, tr( "Save PlayList" ), this, SLOT( saveList() ) ); + new MenuItem( pmPlayList, tr( "Load PlayList" ), this, SLOT( loadList() ) ); +#endif + + QVBox *vbox5 = new QVBox( this ); vbox5->setBackgroundMode( PaletteButton ); + + // Add the playlist area + QVBox *vbox3 = new QVBox( vbox5 ); vbox3->setBackgroundMode( PaletteButton ); + d->playListFrame = vbox3; + + QLabel *plString = new QLabel( tr(" PlayList"), vbox3 ); + plString->setBackgroundMode( QButton::PaletteButton ); + plString->setFont( QFont( "Helvetica", 8, QFont::Bold ) ); + + QHBox *hbox2 = new QHBox( vbox3 ); hbox2->setBackgroundMode( PaletteButton ); + d->selectedFiles = new PlayListSelection( hbox2 ); + QVBox *vbox1 = new QVBox( hbox2 ); vbox1->setBackgroundMode( PaletteButton ); + +#ifndef BUTTONS_ON_TOOLBAR + d->tbPlay = new ToolButton( vbox1, tr( "Play" ), "mpegplayer/play", mediaPlayerState, SLOT(setPlaying(bool)), TRUE ); + QVBox *stretch1 = new QVBox( vbox1 ); stretch1->setBackgroundMode( PaletteButton ); // add stretch +#endif + new ToolButton( vbox1, tr( "Move Up" ), "mpegplayer/up", d->selectedFiles, SLOT(moveSelectedUp()) ); + new ToolButton( vbox1, tr( "Remove" ), "mpegplayer/cut", d->selectedFiles, SLOT(removeSelected()) ); + new ToolButton( vbox1, tr( "Move Down" ), "mpegplayer/down", d->selectedFiles, SLOT(moveSelectedDown()) ); + QVBox *stretch2 = new QVBox( vbox1 ); stretch2->setBackgroundMode( PaletteButton ); // add stretch +#ifndef BUTTONS_ON_TOOLBAR + d->tbShuffle = new ToolButton( vbox1, tr( "Randomize" ), "mpegplayer/shuffle", mediaPlayerState, SLOT(setShuffled(bool)), TRUE ); +#endif + + // add the library area + QVBox *vbox4 = new QVBox( vbox5 ); vbox4->setBackgroundMode( PaletteButton ); + + QLabel *libString = new QLabel( tr(" Media Library"), vbox4 ); + libString->setBackgroundMode( QButton::PaletteButton ); + libString->setFont( QFont( "Helvetica", 8, QFont::Bold ) ); + + QHBox *hbox6 = new QHBox( vbox4 ); hbox6->setBackgroundMode( PaletteButton ); + d->files = new FileSelector( "video/*;audio/*", hbox6, "Find Media Files", FALSE, FALSE ); + d->files->setBackgroundMode( PaletteButton ); + QVBox *vbox7 = new QVBox( hbox6 ); vbox7->setBackgroundMode( PaletteButton ); + +#ifdef SIDE_BUTTONS + new ToolButton( vbox7, tr( "Add to Playlist" ), "mpegplayer/add_to_playlist", d->selectedFiles, SLOT(addSelected()) ); + new ToolButton( vbox7, tr( "Remove from Playlist" ), "mpegplayer/remove_from_playlist", d->selectedFiles, SLOT(removeSelected()) ); + QVBox *stretch3 = new QVBox( vbox1 ); stretch3->setBackgroundMode( PaletteButton ); // add stretch +#endif + + connect( d->files, SIGNAL( fileSelected( const DocLnk & ) ), this, SLOT( addToSelection( const DocLnk & ) ) ); + connect( mediaPlayerState, SIGNAL( playingToggled( bool ) ), d->tbPlay, SLOT( setOn( bool ) ) ); + connect( mediaPlayerState, SIGNAL( loopingToggled( bool ) ), d->tbLoop, SLOT( setOn( bool ) ) ); + connect( mediaPlayerState, SIGNAL( shuffledToggled( bool ) ), d->tbShuffle, SLOT( setOn( bool ) ) ); + connect( mediaPlayerState, SIGNAL( fullscreenToggled( bool ) ), d->tbFull, SLOT( setOn( bool ) ) ); + connect( mediaPlayerState, SIGNAL( scaledToggled( bool ) ), d->tbScale, SLOT( setOn( bool ) ) ); + connect( mediaPlayerState, SIGNAL( fullscreenToggled( bool ) ), d->tbScale, SLOT( setEnabled( bool ) ) ); + connect( mediaPlayerState, SIGNAL( playlistToggled( bool ) ), this, SLOT( setPlaylist( bool ) ) ); + + setCentralWidget( vbox5 ); + + Config cfg( "MediaPlayer" ); + readConfig( cfg ); + + initializeStates(); +} + + +PlayListWidget::~PlayListWidget() { + Config cfg( "MediaPlayer" ); + writeConfig( cfg ); + + if ( d->current ) + delete d->current; + delete d; +} + + +void PlayListWidget::initializeStates() { + d->tbPlay->setOn( mediaPlayerState->playing() ); + d->tbLoop->setOn( mediaPlayerState->looping() ); + d->tbShuffle->setOn( mediaPlayerState->shuffled() ); + d->tbFull->setOn( mediaPlayerState->fullscreen() ); + d->tbScale->setOn( mediaPlayerState->scaled() ); + d->tbScale->setEnabled( mediaPlayerState->fullscreen() ); + setPlaylist( mediaPlayerState->playlist() ); +} + + +void PlayListWidget::readConfig( Config& cfg ) { + cfg.setGroup("PlayList"); + + int noOfFiles = cfg.readNumEntry("NumberOfFiles", 0 ); + + for ( int i = 0; i < noOfFiles; i++ ) { + QString entryName; + entryName.sprintf( "File%i", i + 1 ); + QString linkFile = cfg.readEntry( entryName ); + DocLnk lnk( linkFile ); + if ( lnk.isValid() ) + d->selectedFiles->addToSelection( lnk ); + + } +} + + +void PlayListWidget::writeConfig( Config& cfg ) const { + cfg.setGroup("PlayList"); + + int noOfFiles = 0; + + d->selectedFiles->first(); + do { + const DocLnk *lnk = d->selectedFiles->current(); + if ( lnk ) { + QString entryName; + entryName.sprintf( "File%i", noOfFiles + 1 ); + cfg.writeEntry( entryName, lnk->linkFile() ); + // if this link does exist, add it so we have the file + // next time... + if ( !QFile::exists( lnk->linkFile() ) ) { + // the way writing lnks doesn't really check for out + // of disk space, but check it anyway. + if ( !lnk->writeLink() ) { + QMessageBox::critical( 0, tr("Out of space"), + tr( "There was a problem saving " + "the playlist.\n" + "Your playlist " + "may be missing some entries\n" + "the next time you start it." ) + ); + } + } + noOfFiles++; + } + } while ( d->selectedFiles->next() ); + + cfg.writeEntry("NumberOfFiles", noOfFiles ); +} + + +void PlayListWidget::addToSelection( const DocLnk& lnk ) { + d->setDocumentUsed = FALSE; + if ( mediaPlayerState->playlist() ) + d->selectedFiles->addToSelection( lnk ); + else + mediaPlayerState->setPlaying( TRUE ); +} + + +void PlayListWidget::clearList() { + while ( first() ) + d->selectedFiles->removeSelected(); +} + + +void PlayListWidget::addAllToList() { + DocLnkSet files; + Global::findDocuments(&files, "video/*;audio/*"); + QListIterator dit( files.children() ); + for ( ; dit.current(); ++dit ) + d->selectedFiles->addToSelection( **dit ); +} + + +void PlayListWidget::addAllMusicToList() { + DocLnkSet files; + Global::findDocuments(&files, "audio/*"); + QListIterator dit( files.children() ); + for ( ; dit.current(); ++dit ) + d->selectedFiles->addToSelection( **dit ); +} + + +void PlayListWidget::addAllVideoToList() { + DocLnkSet files; + Global::findDocuments(&files, "video/*"); + QListIterator dit( files.children() ); + for ( ; dit.current(); ++dit ) + d->selectedFiles->addToSelection( **dit ); +} + + +void PlayListWidget::setDocument(const QString& fileref) { + if ( fileref.isNull() ) { + QMessageBox::critical( 0, tr( "Invalid File" ), tr( "There was a problem in getting the file." ) ); + return; + } + if ( mediaPlayerState->playlist() ) + addToSelection( DocLnk( fileref ) ); + else { + d->setDocumentUsed = TRUE; + if ( d->current ) + delete d->current; + d->current = new DocLnk( fileref ); + } + mediaPlayerState->setPlaying( FALSE ); + mediaPlayerState->setPlaying( TRUE ); +} + + +void PlayListWidget::setActiveWindow() { + // When we get raised we need to ensure that it switches views + char origView = mediaPlayerState->view(); + mediaPlayerState->setView( 'l' ); // invalidate + mediaPlayerState->setView( origView ); // now switch back +} + + +void PlayListWidget::useSelectedDocument() { + d->setDocumentUsed = FALSE; +} + + +const DocLnk *PlayListWidget::current() { + if ( mediaPlayerState->playlist() ) + return d->selectedFiles->current(); + else if ( d->setDocumentUsed && d->current ) { + return d->current; + } else + return d->files->selected(); +} + + +bool PlayListWidget::prev() { + if ( mediaPlayerState->playlist() ) { + if ( mediaPlayerState->shuffled() ) { + const DocLnk *cur = current(); + int j = 1 + (int)(97.0 * rand() / (RAND_MAX + 1.0)); + for ( int i = 0; i < j; i++ ) { + if ( !d->selectedFiles->next() ) + d->selectedFiles->first(); + } + if ( cur == current() ) + if ( !d->selectedFiles->next() ) + d->selectedFiles->first(); + return TRUE; + } else { + if ( !d->selectedFiles->prev() ) { + if ( mediaPlayerState->looping() ) { + return d->selectedFiles->last(); + } else { + return FALSE; + } + } + return TRUE; + } + } else { + return mediaPlayerState->looping(); + } +} + + +bool PlayListWidget::next() { + if ( mediaPlayerState->playlist() ) { + if ( mediaPlayerState->shuffled() ) { + return prev(); + } else { + if ( !d->selectedFiles->next() ) { + if ( mediaPlayerState->looping() ) { + return d->selectedFiles->first(); + } else { + return FALSE; + } + } + return TRUE; + } + } else { + return mediaPlayerState->looping(); + } +} + + +bool PlayListWidget::first() { + if ( mediaPlayerState->playlist() ) + return d->selectedFiles->first(); + else + return mediaPlayerState->looping(); +} + + +bool PlayListWidget::last() { + if ( mediaPlayerState->playlist() ) + return d->selectedFiles->last(); + else + return mediaPlayerState->looping(); +} + + +void PlayListWidget::saveList() { + QString filename; +// pseudo code +// filename = QLineEdit->getText(); + Config cfg( filename + ".playlist" ); + writeConfig( cfg ); +} + + +void PlayListWidget::loadList() { + QString filename; +// pseudo code +// filename = FileSelector->openFile( "*.playlist" ); + Config cfg( filename + ".playlist" ); + readConfig( cfg ); +} + + +void PlayListWidget::setPlaylist( bool shown ) { + if ( shown ) + d->playListFrame->show(); + else + d->playListFrame->hide(); +} + + +void PlayListWidget::setView( char view ) { + if ( view == 'l' ) + showMaximized(); + else + hide(); +} + diff --git a/core/multimedia/opieplayer/playlistwidget.h b/core/multimedia/opieplayer/playlistwidget.h new file mode 100644 index 0000000..6976641 --- a/dev/null +++ b/core/multimedia/opieplayer/playlistwidget.h @@ -0,0 +1,68 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef PLAY_LIST_WIDGET_H +#define PLAY_LIST_WIDGET_H + + +#include +#include + + +class PlayListWidgetPrivate; +class Config; + + +class PlayListWidget : public QMainWindow { + Q_OBJECT +public: + PlayListWidget( QWidget* parent=0, const char* name=0, WFlags fl=0 ); + ~PlayListWidget(); + + // retrieve the current playlist entry (media file link) + const DocLnk *current(); + void useSelectedDocument(); + +public slots: + void setDocument( const QString& fileref ); + void addToSelection( const DocLnk& ); // Add a media file to the playlist + void setActiveWindow(); // need to handle this to show the right view + void setPlaylist( bool ); // Show/Hide the playlist + void setView( char ); + void clearList(); + void addAllToList(); + void addAllMusicToList(); + void addAllVideoToList(); + void saveList(); // Save the playlist + void loadList(); // Load a playlist + bool first(); + bool last(); + bool next(); + bool prev(); + +private: + void initializeStates(); + void readConfig( Config& cfg ); + void writeConfig( Config& cfg ) const; + PlayListWidgetPrivate *d; // Private implementation data +}; + + +#endif // PLAY_LIST_WIDGET_H + diff --git a/core/multimedia/opieplayer/qpe-mpegplayer.control b/core/multimedia/opieplayer/qpe-mpegplayer.control new file mode 100644 index 0000000..2cad8ab --- a/dev/null +++ b/core/multimedia/opieplayer/qpe-mpegplayer.control @@ -0,0 +1,9 @@ +Files: bin/mpegplayer pics/mpegplayer/* apps/Applications/mpegplayer.desktop plugins/codecs/libmpeg3plugin.so plugins/codecs/libmpeg3plugin.so.1 plugins/codecs/libmpeg3plugin.so.1.0 plugins/codecs/libmpeg3plugin.so.1.0.0 +Priority: optional +Section: qpe/applications +Maintainer: John Ryland +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: MPEG video/audio player + The mpegplayer for the Qtopia environment. diff --git a/core/multimedia/opieplayer/videowidget.cpp b/core/multimedia/opieplayer/videowidget.cpp new file mode 100644 index 0000000..f3974a0 --- a/dev/null +++ b/core/multimedia/opieplayer/videowidget.cpp @@ -0,0 +1,423 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#include +#include +#include +#include +#include +#include "videowidget.h" +#include "mediaplayerplugininterface.h" +#include "mediaplayerstate.h" + + +#ifdef Q_WS_QWS +# define USE_DIRECT_PAINTER +# include +# include +#endif + + +extern MediaPlayerState *mediaPlayerState; + + +static const int xo = 2; // movable x offset +static const int yo = 0; // movable y offset + + +struct MediaButton { + int xPos, yPos; + bool isToggle, isHeld, isDown; + int controlType; +}; + + +// Layout information for the videoButtons (and if it is a toggle button or not) +MediaButton videoButtons[] = { + { 5+0*32+xo, 200+yo, FALSE, FALSE, FALSE, 4 }, // previous + { 5+1*32+xo, 200+yo, FALSE, FALSE, FALSE, 1 }, // stop + { 5+2*32+xo, 200+yo, TRUE, FALSE, FALSE, 0 }, // play + { 5+3*32+xo, 200+yo, TRUE, FALSE, FALSE, 2 }, // pause + { 5+4*32+xo, 200+yo, FALSE, FALSE, FALSE, 3 }, // next + { 5+5*32+xo, 200+yo, FALSE, FALSE, FALSE, 8 }, // playlist + { 5+6*32+xo, 200+yo, TRUE, FALSE, FALSE, 9 } // fullscreen +}; + + +static const int numButtons = (sizeof(videoButtons)/sizeof(MediaButton)); + + +VideoWidget::VideoWidget(QWidget* parent, const char* name, WFlags f) : + QWidget( parent, name, f ), scaledWidth( 0 ), scaledHeight( 0 ) { + setCaption( tr("MediaPlayer") ); + setBackgroundPixmap( Resource::loadPixmap( "mpegplayer/metalFinish" ) ); + pixmaps[0] = new QPixmap( Resource::loadPixmap( "mpegplayer/mediaButton0a" ) ); + pixmaps[1] = new QPixmap( Resource::loadPixmap( "mpegplayer/mediaButton0b" ) ); + pixmaps[2] = new QPixmap( Resource::loadPixmap( "mpegplayer/mediaControls0" ) ); + currentFrame = new QImage( 220 + 2, 160, (QPixmap::defaultDepth() == 16) ? 16 : 32 ); + + slider = new QSlider( Qt::Horizontal, this ); + slider->setMinValue( 0 ); + slider->setMaxValue( 1 ); + slider->setBackgroundPixmap( Resource::loadPixmap( "mpegplayer/metalFinish" ) ); + slider->setFocusPolicy( QWidget::NoFocus ); + slider->setGeometry( QRect( 7, 250, 220, 20 ) ); + + connect( slider, SIGNAL( sliderPressed() ), this, SLOT( sliderPressed() ) ); + connect( slider, SIGNAL( sliderReleased() ), this, SLOT( sliderReleased() ) ); + + connect( mediaPlayerState, SIGNAL( lengthChanged(long) ), this, SLOT( setLength(long) ) ); + connect( mediaPlayerState, SIGNAL( positionChanged(long) ),this, SLOT( setPosition(long) ) ); + connect( mediaPlayerState, SIGNAL( positionUpdated(long) ),this, SLOT( setPosition(long) ) ); + connect( mediaPlayerState, SIGNAL( viewChanged(char) ), this, SLOT( setView(char) ) ); + connect( mediaPlayerState, SIGNAL( pausedToggled(bool) ), this, SLOT( setPaused(bool) ) ); + connect( mediaPlayerState, SIGNAL( playingToggled(bool) ), this, SLOT( setPlaying(bool) ) ); + + // Intialise state + setLength( mediaPlayerState->length() ); + setPosition( mediaPlayerState->position() ); + setFullscreen( mediaPlayerState->fullscreen() ); + setPaused( mediaPlayerState->paused() ); + setPlaying( mediaPlayerState->playing() ); +} + + +VideoWidget::~VideoWidget() { + for ( int i = 0; i < 3; i++ ) + delete pixmaps[i]; + delete currentFrame; +} + + +static bool videoSliderBeingMoved = FALSE; + + +void VideoWidget::sliderPressed() { + videoSliderBeingMoved = TRUE; +} + + +void VideoWidget::sliderReleased() { + videoSliderBeingMoved = FALSE; + if ( slider->width() == 0 ) + return; + long val = long((double)slider->value() * mediaPlayerState->length() / slider->width()); + mediaPlayerState->setPosition( val ); +} + + +void VideoWidget::setPosition( long i ) { + updateSlider( i, mediaPlayerState->length() ); +} + + +void VideoWidget::setLength( long max ) { + updateSlider( mediaPlayerState->position(), max ); +} + + +void VideoWidget::setView( char view ) { + if ( view == 'v' ) { + makeVisible(); + } else { + // Effectively blank the view next time we show it so it looks nicer + scaledWidth = 0; + scaledHeight = 0; + hide(); + } +} + + +void VideoWidget::updateSlider( long i, long max ) { + // Will flicker too much if we don't do this + if ( max == 0 ) + return; + int width = slider->width(); + int val = int((double)i * width / max); + if ( !mediaPlayerState->fullscreen() && !videoSliderBeingMoved ) { + if ( slider->value() != val ) + slider->setValue( val ); + if ( slider->maxValue() != width ) + slider->setMaxValue( width ); + } +} + + +void VideoWidget::setToggleButton( int i, bool down ) { + if ( down != videoButtons[i].isDown ) + toggleButton( i ); +} + + +void VideoWidget::toggleButton( int i ) { + videoButtons[i].isDown = !videoButtons[i].isDown; + QPainter p(this); + paintButton ( &p, i ); +} + + +void VideoWidget::paintButton( QPainter *p, int i ) { + int x = videoButtons[i].xPos; + int y = videoButtons[i].yPos; + int offset = 10 + videoButtons[i].isDown; + p->drawPixmap( x, y, *pixmaps[videoButtons[i].isDown] ); + p->drawPixmap( x + 1 + offset, y + offset, *pixmaps[2], 9 * videoButtons[i].controlType, 0, 9, 9 ); +} + + +void VideoWidget::mouseMoveEvent( QMouseEvent *event ) { + for ( int i = 0; i < numButtons; i++ ) { + int x = videoButtons[i].xPos; + int y = videoButtons[i].yPos; + if ( event->state() == QMouseEvent::LeftButton ) { + // The test to see if the mouse click is inside the circular button or not + // (compared with the radius squared to avoid a square-root of our distance) + int radius = 16; + QPoint center = QPoint( x + radius, y + radius ); + QPoint dXY = center - event->pos(); + int dist = dXY.x() * dXY.x() + dXY.y() * dXY.y(); + bool isOnButton = dist <= (radius * radius); + if ( isOnButton != videoButtons[i].isHeld ) { + videoButtons[i].isHeld = isOnButton; + toggleButton(i); + } + } else { + if ( videoButtons[i].isHeld ) { + videoButtons[i].isHeld = FALSE; + if ( !videoButtons[i].isToggle ) + setToggleButton( i, FALSE ); + switch (i) { + case VideoPlay: mediaPlayerState->setPlaying(videoButtons[i].isDown); return; + case VideoStop: mediaPlayerState->setPlaying(FALSE); return; + case VideoPause: mediaPlayerState->setPaused(videoButtons[i].isDown); return; + case VideoNext: mediaPlayerState->setNext(); return; + case VideoPrevious: mediaPlayerState->setPrev(); return; + case VideoPlayList: mediaPlayerState->setList(); return; + case VideoFullscreen: mediaPlayerState->setFullscreen( TRUE ); makeVisible(); return; + } + } + } + } +} + + +void VideoWidget::mousePressEvent( QMouseEvent *event ) { + mouseMoveEvent( event ); +} + + +void VideoWidget::mouseReleaseEvent( QMouseEvent *event ) { + if ( mediaPlayerState->fullscreen() ) { + mediaPlayerState->setFullscreen( FALSE ); + makeVisible(); + } else { + mouseMoveEvent( event ); + } +} + + +void VideoWidget::makeVisible() { + if ( mediaPlayerState->fullscreen() ) { + setBackgroundMode( QWidget::NoBackground ); + showFullScreen(); + resize( qApp->desktop()->size() ); + slider->hide(); + } else { + setBackgroundPixmap( Resource::loadPixmap( "mpegplayer/metalFinish" ) ); + showNormal(); + showMaximized(); + slider->show(); + } +} + + +void VideoWidget::paintEvent( QPaintEvent * ) { + QPainter p( this ); + + if ( mediaPlayerState->fullscreen() ) { + // Clear the background + p.setBrush( QBrush( Qt::black ) ); + p.drawRect( rect() ); + + // Draw the current frame + //p.drawImage( ); // If using directpainter we won't have a copy except whats on the screen + } else { + // draw border + qDrawShadePanel( &p, 4, 15, 230, 170, colorGroup(), TRUE, 5, NULL ); + + // Clear the movie screen first + p.setBrush( QBrush( Qt::black ) ); + p.drawRect( 9, 20, 220, 160 ); + + // draw current frame (centrally positioned from scaling to maintain aspect ratio) + p.drawImage( 9 + (220 - scaledWidth) / 2, 20 + (160 - scaledHeight) / 2, *currentFrame, 0, 0, scaledWidth, scaledHeight ); + + // draw the buttons + for ( int i = 0; i < numButtons; i++ ) + paintButton( &p, i ); + + // draw the slider + slider->repaint( TRUE ); + } +} + + +void VideoWidget::closeEvent( QCloseEvent* ) { + mediaPlayerState->setList(); +} + + +bool VideoWidget::playVideo() { + bool result = FALSE; + + int stream = 0; + + int sw = mediaPlayerState->curDecoder()->videoWidth( stream ); + int sh = mediaPlayerState->curDecoder()->videoHeight( stream ); + int dd = QPixmap::defaultDepth(); + int w = height(); + int h = width(); + + ColorFormat format = (dd == 16) ? RGB565 : BGRA8888; + + if ( mediaPlayerState->fullscreen() ) { +#ifdef USE_DIRECT_PAINTER + QDirectPainter p(this); + + if ( ( qt_screen->transformOrientation() == 3 ) && + ( ( dd == 16 ) || ( dd == 32 ) ) && ( p.numRects() == 1 ) ) { + + w = 320; + h = 240; + + if ( mediaPlayerState->scaled() ) { + // maintain aspect ratio + if ( w * sh > sw * h ) + w = sw * h / sh; + else + h = sh * w / sw; + } else { + w = sw; + h = sh; + } + + w--; // we can't allow libmpeg to overwrite. + QPoint roff = qt_screen->mapToDevice( p.offset(), QSize( qt_screen->width(), qt_screen->height() ) ); + + int ox = roff.x() - height() + 2 + (height() - w) / 2; + int oy = roff.y() + (width() - h) / 2; + int sx = 0, sy = 0; + + uchar* fp = p.frameBuffer() + p.lineStep() * oy; + fp += dd * ox / 8; + uchar **jt = new uchar*[h]; + for ( int i = h; i; i-- ) { + jt[h - i] = fp; + fp += p.lineStep(); + } + + result = mediaPlayerState->curDecoder()->videoReadScaledFrame( jt, sx, sy, sw, sh, w, h, format, 0) == 0; + + delete [] jt; + } else { +#endif + QPainter p(this); + + w = 320; + h = 240; + + if ( mediaPlayerState->scaled() ) { + // maintain aspect ratio + if ( w * sh > sw * h ) + w = sw * h / sh; + else + h = sh * w / sw; + } else { + w = sw; + h = sh; + } + + int bytes = ( dd == 16 ) ? 2 : 4; + QImage tempFrame( w, h, bytes << 3 ); + result = mediaPlayerState->curDecoder()->videoReadScaledFrame( tempFrame.jumpTable(), + 0, 0, sw, sh, w, h, format, 0) == 0; + if ( result && mediaPlayerState->fullscreen() ) { + + int rw = h, rh = w; + QImage rotatedFrame( rw, rh, bytes << 3 ); + + ushort* in = (ushort*)tempFrame.bits(); + ushort* out = (ushort*)rotatedFrame.bits(); + int spl = rotatedFrame.bytesPerLine() / bytes; + for (int x=0; x sw * h ) + w = sw * h / sh; + else + h = sh * w / sw; + + result = mediaPlayerState->curDecoder()->videoReadScaledFrame( currentFrame->jumpTable(), 0, 0, sw, sh, w, h, format, 0) == 0; + + QPainter p( this ); + + // Image changed size, therefore need to blank the possibly unpainted regions first + if ( scaledWidth != w || scaledHeight != h ) { + p.setBrush( QBrush( Qt::black ) ); + p.drawRect( 9, 20, 220, 160 ); + } + + scaledWidth = w; + scaledHeight = h; + + if ( result ) { + p.drawImage( 9 + (220 - scaledWidth) / 2, 20 + (160 - scaledHeight) / 2, *currentFrame, 0, 0, scaledWidth, scaledHeight ); + } + + } + + return result; +} + + diff --git a/core/multimedia/opieplayer/videowidget.h b/core/multimedia/opieplayer/videowidget.h new file mode 100644 index 0000000..8b49091 --- a/dev/null +++ b/core/multimedia/opieplayer/videowidget.h @@ -0,0 +1,88 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef VIDEO_WIDGET_H +#define VIDEO_WIDGET_H + + +#include + + +class QPixmap; +class QSlider; + + +enum VideoButtons { + VideoPrevious, + VideoStop, + VideoPlay, + VideoPause, + VideoNext, + VideoPlayList, + VideoFullscreen +}; + + +class VideoWidget : public QWidget { + Q_OBJECT +public: + VideoWidget( QWidget* parent=0, const char* name=0, WFlags f=0 ); + ~VideoWidget(); + + bool playVideo(); + +public slots: + void updateSlider( long, long ); + void sliderPressed( ); + void sliderReleased( ); + void setPaused( bool b) { setToggleButton( VideoPause, b ); } + void setPlaying( bool b) { setToggleButton( VideoPlay, b ); } + void setFullscreen( bool b ) { setToggleButton( VideoFullscreen, b ); } + void makeVisible(); + void setPosition( long ); + void setLength( long ); + void setView( char ); + +signals: + void sliderMoved( long ); + +protected: + void paintEvent( QPaintEvent *pe ); + void mouseMoveEvent( QMouseEvent *event ); + void mousePressEvent( QMouseEvent *event ); + void mouseReleaseEvent( QMouseEvent *event ); + void closeEvent( QCloseEvent *event ); + +private: + void paintButton( QPainter *p, int i ); + void toggleButton( int ); + void setToggleButton( int, bool ); + + QSlider *slider; + QPixmap *pixmaps[3]; + QImage *currentFrame; + int scaledWidth; + int scaledHeight; +}; + + +#endif // VIDEO_WIDGET_H + + + diff --git a/core/multimedia/opieplayer/wavplugin/.cvsignore b/core/multimedia/opieplayer/wavplugin/.cvsignore new file mode 100644 index 0000000..6fe2396 --- a/dev/null +++ b/core/multimedia/opieplayer/wavplugin/.cvsignore @@ -0,0 +1,2 @@ +moc_* +Makefile diff --git a/core/multimedia/opieplayer/wavplugin/Makefile.in b/core/multimedia/opieplayer/wavplugin/Makefile.in new file mode 100644 index 0000000..c9203f8 --- a/dev/null +++ b/core/multimedia/opieplayer/wavplugin/Makefile.in @@ -0,0 +1,112 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB) -DQCONFIG=\"qpe\" +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB) -DQCONFIG=\"qpe\" +INCPATH = -I$(QPEDIR)/include -I.. +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../../plugins/codecs/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = wavplugin +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = wavplugin.h \ + wavpluginimpl.h +SOURCES = wavplugin.cpp \ + wavpluginimpl.cpp +OBJECTS = wavplugin.o \ + wavpluginimpl.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = +OBJMOC = + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(SYSCONF_LINK_TARGET) + +$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK_LIB) + +moc: $(SRCMOC) + +tmake: + tmake wavplugin.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +wavplugin.o: wavplugin.cpp \ + wavplugin.h \ + ../mediaplayerplugininterface.h + +wavpluginimpl.o: wavpluginimpl.cpp \ + wavplugin.h \ + ../mediaplayerplugininterface.h \ + wavpluginimpl.h \ + ../mediaplayerplugininterface.h + + diff --git a/core/multimedia/opieplayer/wavplugin/qpe-wavplugin.control b/core/multimedia/opieplayer/wavplugin/qpe-wavplugin.control new file mode 100644 index 0000000..8e7eedb --- a/dev/null +++ b/core/multimedia/opieplayer/wavplugin/qpe-wavplugin.control @@ -0,0 +1,9 @@ +Files: plugins/codecs/libwavplugin.so.1.0.0 plugins/codecs/libwavplugin.so.1.0 plugins/codecs/libwavplugin.so.1 plugins/codecs/libwavplugin.so +Priority: optional +Section: qpe/plugins +Maintainer: John Ryland +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: WAV file plugin + Plugin to play WAV files with the mediaplayer in the Qtopia environment. diff --git a/core/multimedia/opieplayer/wavplugin/wavplugin.cpp b/core/multimedia/opieplayer/wavplugin/wavplugin.cpp new file mode 100644 index 0000000..60a0024 --- a/dev/null +++ b/core/multimedia/opieplayer/wavplugin/wavplugin.cpp @@ -0,0 +1,334 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include +#include +#include +#include +#include +#include +#include "wavplugin.h" + + +//#define debugMsg(a) qDebug(a) +#define debugMsg(a) + + +struct RiffChunk { + char id[4]; + Q_UINT32 size; + char data[4]; +}; + + +struct ChunkData { + Q_INT16 formatTag; + Q_INT16 channels; + Q_INT32 samplesPerSec; + Q_INT32 avgBytesPerSec; + Q_INT16 blockAlign; + Q_INT16 wBitsPerSample; +}; + + +const int sound_buffer_size = 4096; + + +class WavPluginData { +public: + QFile *input; + + int wavedata_remaining; + ChunkData chunkdata; + RiffChunk chunk; + uchar data[sound_buffer_size+32]; // +32 to handle badly aligned input data + int out,max; + int samples_due; + int samples; + + WavPluginData() { + max = out = sound_buffer_size; + wavedata_remaining = 0; + samples_due = 0; + samples = -1; + } + + // expands out samples to the frequency of 44kHz + bool add( short *output, long count, long& done, bool stereo ) + { + done = 0; + + if ( input == 0 ) { + qDebug("no input"); + return FALSE; + } + + while ( count ) { + int l,r; + if ( getSample(l, r) == FALSE ) { + qDebug("didn't get sample"); + return FALSE; + } + samples_due += 44100; + while ( count && (samples_due > chunkdata.samplesPerSec) ) { + *output++ = l; + if ( stereo ) + *output++ = r; + samples_due -= chunkdata.samplesPerSec; + count--; + done++; + } + } + + return TRUE; + } + + bool initialise() { + if ( input == 0 ) + return FALSE; + + wavedata_remaining = -1; + + while ( wavedata_remaining == -1 ) { + // Keep reading chunks... + const int n = sizeof(chunk) - sizeof(chunk.data); + int t = input->readBlock( (char*)&chunk, n ); + if ( t != n ) { + if ( t == -1 ) + return FALSE; + return TRUE; + } + if ( qstrncmp(chunk.id,"data",4) == 0 ) { + samples = wavedata_remaining = chunk.size; + } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) { + char d[4]; + if ( input->readBlock(d,4) != 4 ) { + return FALSE; + } + if ( qstrncmp(d,"WAVE",4) != 0 ) { + // skip + if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size-4) ) { + return FALSE; + } + } + } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) { + if ( input->readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) ) { + return FALSE; + } +#define WAVE_FORMAT_PCM 1 + if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) { + qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag); + return FALSE; + } + } else { + // ignored chunk + if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size) ) { + return FALSE; + } + } + } // while + + return TRUE; + } + + + // gets a sample from the file + bool getSample(int& l, int& r) + { + l = r = 0; + + if ( input == 0 ) + return FALSE; + + if ( (wavedata_remaining < 0) || !max ) + return FALSE; + + if ( out >= max ) { + max = input->readBlock( (char*)data, (uint)QMIN(sound_buffer_size,wavedata_remaining) ); + + wavedata_remaining -= max; + + out = 0; + if ( max <= 0 ) { + max = 0; + return TRUE; + } + } + if ( chunkdata.wBitsPerSample == 8 ) { + l = (data[out++] - 128) * 128; + } else { + l = ((short*)data)[out/2]; + out += 2; + } + if ( chunkdata.channels == 1 ) { + r = l; + } else { + if ( chunkdata.wBitsPerSample == 8 ) { + r = (data[out++] - 128) * 128; + } else { + r = ((short*)data)[out/2]; + out += 2; + } + } + return TRUE; + } // getSample + +}; + + +WavPlugin::WavPlugin() { + d = new WavPluginData; + d->input = 0; +} + + +WavPlugin::~WavPlugin() { + close(); + delete d; +} + + +bool WavPlugin::isFileSupported( const QString& path ) { + debugMsg( "WavPlugin::isFileSupported" ); + + char *ext = strrchr( path.latin1(), '.' ); + + // Test file extension + if ( ext ) { + if ( strncasecmp(ext, ".raw", 4) == 0 ) + return TRUE; + if ( strncasecmp(ext, ".wav", 4) == 0 ) + return TRUE; + if ( strncasecmp(ext, ".wave", 4) == 0 ) + return TRUE; + } + + return FALSE; +} + + +bool WavPlugin::open( const QString& path ) { + debugMsg( "WavPlugin::open" ); + + d->max = d->out = sound_buffer_size; + d->wavedata_remaining = 0; + d->samples_due = 0; + + d->input = new QFile( path ); + if ( d->input->open(IO_ReadOnly) == FALSE ) { + qDebug("couldn't open file"); + delete d->input; + d->input = 0; + return FALSE; + } + + d->initialise(); + + return TRUE; +} + + +bool WavPlugin::close() { + debugMsg( "WavPlugin::close" ); + + d->input->close(); + delete d->input; + d->input = 0; + return TRUE; +} + + +bool WavPlugin::isOpen() { + debugMsg( "WavPlugin::isOpen" ); + return ( d->input != 0 ); +} + + +int WavPlugin::audioStreams() { + debugMsg( "WavPlugin::audioStreams" ); + return 1; +} + + +int WavPlugin::audioChannels( int ) { + debugMsg( "WavPlugin::audioChannels" ); + return 2; // ### Always scale audio to stereo samples +} + + +int WavPlugin::audioFrequency( int ) { + debugMsg( "WavPlugin::audioFrequency" ); + return 44100; // ### Always scale to frequency of 44100 +} + + +int WavPlugin::audioSamples( int ) { + debugMsg( "WavPlugin::audioSamples" ); + return d->samples * 2 / d->chunkdata.channels; // ### Scaled samples will be made stereo, + // Therefore if source is mono we will double the number of samples +} + + +bool WavPlugin::audioSetSample( long, int ) { + debugMsg( "WavPlugin::audioSetSample" ); + return FALSE; +} + + +long WavPlugin::audioGetSample( int ) { + debugMsg( "WavPlugin::audioGetSample" ); + return 0; +} + +/* +bool WavPlugin::audioReadSamples( short *, int, long, int ) { + debugMsg( "WavPlugin::audioReadSamples" ); + return FALSE; +} + + +bool WavPlugin::audioReReadSamples( short *, int, long, int ) { + debugMsg( "WavPlugin::audioReReadSamples" ); + return FALSE; +} + + +bool WavPlugin::audioReadMonoSamples( short *output, long samples, long& samplesMade, int ) { + debugMsg( "WavPlugin::audioReadMonoSamples" ); + return !d->add( output, samples, samplesMade, FALSE ); +} + + +bool WavPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) { + debugMsg( "WavPlugin::audioReadStereoSamples" ); + return !d->add( output, samples, samplesMade, TRUE ); +} +*/ + +bool WavPlugin::audioReadSamples( short *output, int channels, long samples, long& samplesMade, int ) { + debugMsg( "WavPlugin::audioReadSamples" ); + return !d->add( output, samples, samplesMade, channels != 1 ); +} + +double WavPlugin::getTime() { + debugMsg( "WavPlugin::getTime" ); + return 0.0; +} + + diff --git a/core/multimedia/opieplayer/wavplugin/wavplugin.h b/core/multimedia/opieplayer/wavplugin/wavplugin.h new file mode 100644 index 0000000..64635ca --- a/dev/null +++ b/core/multimedia/opieplayer/wavplugin/wavplugin.h @@ -0,0 +1,97 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef WAV_PLUGIN_H +#define WAV_PLUGIN_H + + +#include +#include +#include "mediaplayerplugininterface.h" + + +class WavPluginData; + + +class WavPlugin : public MediaPlayerDecoder { + +public: + WavPlugin(); + ~WavPlugin(); + + const char *pluginName() { return "WavPlugin"; } + const char *pluginComment() { return "This is a simple plugin for playing wav files"; } + double pluginVersion() { return 1.0; } + + bool isFileSupported( const QString& ); + bool open( const QString& ); + bool close(); + bool isOpen(); + //const QString &fileInfo() { return strInfo = qApp->translate( "MediaPlayer", "No Information Available", "media plugin text" ); } + const QString &fileInfo() { return strInfo = QString(""); } + + // If decoder doesn't support audio then return 0 here + int audioStreams(); + int audioChannels( int stream ); + int audioFrequency( int stream ); + int audioSamples( int stream ); + bool audioSetSample( long sample, int stream ); + long audioGetSample( int stream ); + //bool audioReadMonoSamples( short *output, long samples, long& samplesRead, int stream ); + //bool audioReadStereoSamples( short *output, long samples, long& samplesRead, int stream ); + bool audioReadSamples( short *output, int channels, long samples, long& samplesRead, int stream ); + //bool audioReadSamples( short *output, int channel, long samples, int stream ); + //bool audioReReadSamples( short *output, int channel, long samples, int stream ); + + // If decoder doesn't support video then return 0 here + int videoStreams() { return 0; } + int videoWidth( int ) { return 0; } + int videoHeight( int ) { return 0; } + double videoFrameRate( int ) { return 0.0; } + int videoFrames( int ) { return 0; } + bool videoSetFrame( long, int ) { return FALSE; } + long videoGetFrame( int ) { return 0; } + bool videoReadFrame( unsigned char **, int, int, int, int, ColorFormat, int ) { return FALSE; } + bool videoReadScaledFrame( unsigned char **, int, int, int, int, int, int, ColorFormat, int ) { return FALSE; } + bool videoReadYUVFrame( char *, char *, char *, int, int, int, int, int ) { return FALSE; } + + // Profiling + double getTime(); + + // Ignore if these aren't supported + bool setSMP( int ) { return FALSE; } + bool setMMX( bool ) { return FALSE; } + + // Capabilities + bool supportsAudio() { return TRUE; } + bool supportsVideo() { return FALSE; } + bool supportsYUV() { return FALSE; } + bool supportsMMX() { return TRUE; } + bool supportsSMP() { return FALSE; } + bool supportsStereo() { return TRUE; } + bool supportsScaling() { return FALSE; } + +private: + WavPluginData *d; + QString strInfo; + +}; + + +#endif diff --git a/core/multimedia/opieplayer/wavplugin/wavplugin.pro b/core/multimedia/opieplayer/wavplugin/wavplugin.pro new file mode 100644 index 0000000..4663813 --- a/dev/null +++ b/core/multimedia/opieplayer/wavplugin/wavplugin.pro @@ -0,0 +1,10 @@ +TEMPLATE = lib +CONFIG += qt warn_on release +HEADERS = wavplugin.h wavpluginimpl.h +SOURCES = wavplugin.cpp wavpluginimpl.cpp +TARGET = wavplugin +DESTDIR = ../../plugins/codecs +INCLUDEPATH += $(QPEDIR)/include .. +DEPENDPATH += ../$(QPEDIR)/include .. +LIBS += -lqpe +VERSION = 1.0.0 diff --git a/core/multimedia/opieplayer/wavplugin/wavpluginimpl.cpp b/core/multimedia/opieplayer/wavplugin/wavpluginimpl.cpp new file mode 100644 index 0000000..1f7b85b --- a/dev/null +++ b/core/multimedia/opieplayer/wavplugin/wavpluginimpl.cpp @@ -0,0 +1,70 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "wavplugin.h" +#include "wavpluginimpl.h" + + +WavPluginImpl::WavPluginImpl() + : libmadplugin(0), ref(0) +{ +} + + +WavPluginImpl::~WavPluginImpl() +{ + if ( libmadplugin ) + delete libmadplugin; +} + + +MediaPlayerDecoder *WavPluginImpl::decoder() +{ + if ( !libmadplugin ) + libmadplugin = new WavPlugin; + return libmadplugin; +} + + +MediaPlayerEncoder *WavPluginImpl::encoder() +{ + return NULL; +} + + +#ifndef QT_NO_COMPONENT + + +QRESULT WavPluginImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ + *iface = 0; + if ( ( uuid == IID_QUnknown ) || ( uuid == IID_MediaPlayerPlugin ) ) + *iface = this, (*iface)->addRef(); + return QS_OK; +} + + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( WavPluginImpl ) +} + + +#endif + diff --git a/core/multimedia/opieplayer/wavplugin/wavpluginimpl.h b/core/multimedia/opieplayer/wavplugin/wavpluginimpl.h new file mode 100644 index 0000000..ee32f54 --- a/dev/null +++ b/core/multimedia/opieplayer/wavplugin/wavpluginimpl.h @@ -0,0 +1,53 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef WAV_PLUGIN_IMPL_H +#define WAV_PLUGIN_IMPL_H + + +#include "../mediaplayerplugininterface.h" + + +class WavPlugin; + + +class WavPluginImpl : public MediaPlayerPluginInterface +{ +public: + WavPluginImpl(); + virtual ~WavPluginImpl(); + +#ifndef QT_NO_COMPONENT + + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT + +#endif + + virtual MediaPlayerDecoder *decoder(); + virtual MediaPlayerEncoder *encoder(); + +private: + WavPlugin *libmadplugin; + ulong ref; +}; + + +#endif + diff --git a/core/opie-login/.cvsignore b/core/opie-login/.cvsignore new file mode 100644 index 0000000..edfa921 --- a/dev/null +++ b/core/opie-login/.cvsignore @@ -0,0 +1,3 @@ +moc_* +*.moc +Makefile diff --git a/core/opie-login/README b/core/opie-login/README new file mode 100644 index 0000000..ad3b298 --- a/dev/null +++ b/core/opie-login/README @@ -0,0 +1,78 @@ + +Welcome to LISA System's + + QDM - the Login-Dialog for QPE + + +WHAT'S THIS: + +This small add-on for the Qtopia Environment (QPE - see +http://qpe.sourceforge.net for further details) allows You to use your +handheld computer running QPE and Linux with the typical Un*x user +handling, i.e. just log in on a graphical environment, as e.g. KDM or +XDM. This way your personal data can be easily protected against +unwanted access from others in case you loose your machine. + + +STATUS: + +Still in development, but should be useable. + + +REQUIREMENTS: + +- QDM needs Linux-PAM (Pluggable Authentication Modules for Linux) for + proper user validation. + +- the /dev/fb0 device has to writeable to everyone ;-( + + +INSTALLATION: + +Per default this little add-on is not enabled. You have to do so +yourself for now, by setting a compile option variable called +QT_QWS_LOGIN . Furthermore there have to be made some changes in +taskbar/taskbar.pro : + +At the section HEADERS insert a line: + ../login/qdmdialogimpl.h \ + +At the section SOURCES insert a line: + ../login/qdmdialogimpl.cpp \ + +furthermore serte these lines: + +INCLUDEPATH += ../login +DEPENDPATH += ../login + +INTERFACES = ../login/qdmdialog.ui + +For unix-login make folloing changes to a line: +LIBS = -lqpe -lcrypt + +For PAM use the following: +LIBS = -lqpe -ldl -lpam + + + +CONFIGURATION: + +Configuration of the 'Look' of QDM is done via Qt Designer. Just open +the .ui file and edit the look of the dialog as you like. You can, for +instance, change the logo pixmap. QDM should also be ready for i18n so +far. + +Other configuration stuff, eg welcome string in the upper right, and +user list can be changed in the qdm_config.h file. + + +USAGE: + +The QDM comes up, when the QPE is started, and if the QPE is started +as 'root'. Being started as any other user, the uid couldn't be +changed and the login dialog wouldn't be ofg much use. + + +CONTACT: + +http://www.lisa.de diff --git a/core/opie-login/qdm_config.h b/core/opie-login/qdm_config.h new file mode 100644 index 0000000..bf5b5a4 --- a/dev/null +++ b/core/opie-login/qdm_config.h @@ -0,0 +1,30 @@ +//-- -*- c++ -*- + +#ifndef _QDM_CONFIG_H +#define _QDM_CONFIG_H + +/* + * Config file for QDM + */ + + +/** define this to enable the qdm login dialog for qpe */ +#define QT_QWS_LOGIN + +/** define this to let qdm use Linux-PAM */ +//define QT_QWS_LOGIN_USEPAM + +/** this is the list of users shown in the input-list */ +#define QDM_SHOWNUSERS static char *Shown_Users[] = { "guest", "root", "lisa", 0 }; + +/** which command to execute when going to sleep mode */ +#define QDM_CMD_SLEEP "/sbin/shutdow","-z","now" + +/** which command to execute when shutting down */ +#define QDM_CMD_SHUTDOWN "/sbin/shutdow","-z","now" + +/** Welcome string on dialog */ +#define QDM_WELCOME_STRING "Welcome to\nmLinux [iPAQ]" + + +#endif //-- _QDM_CONFIG_H diff --git a/core/opie-login/qdmdialog.ui b/core/opie-login/qdmdialog.ui new file mode 100644 index 0000000..c9faf6f --- a/dev/null +++ b/core/opie-login/qdmdialog.ui @@ -0,0 +1,856 @@ + +QDMDialog + + QDialog + + name + QDMDialog + + + geometry + + 0 + 7 + 240 + 320 + + + + sizePolicy + + 0 + 1 + + + + minimumSize + + 240 + 240 + + + + maximumSize + + 240 + 320 + + + + palette + + + + 0 + 0 + 0 + + + 228 + 228 + 228 + + + 255 + 255 + 255 + + + 242 + 242 + 242 + + + 78 + 78 + 78 + + + 183 + 183 + 183 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 220 + 220 + 220 + + + 0 + 0 + 0 + + + 10 + 95 + 137 + + + 255 + 255 + 255 + + + + + 0 + 0 + 0 + + + 228 + 228 + 228 + + + 255 + 255 + 255 + + + 242 + 242 + 242 + + + 78 + 78 + 78 + + + 183 + 183 + 183 + + + 183 + 183 + 183 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 220 + 220 + 220 + + + 0 + 0 + 0 + + + 0 + 0 + 128 + + + 255 + 255 + 255 + + + + + 0 + 0 + 0 + + + 228 + 228 + 228 + + + 255 + 255 + 255 + + + 242 + 242 + 242 + + + 78 + 78 + 78 + + + 183 + 183 + 183 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 220 + 220 + 220 + + + 0 + 0 + 0 + + + 10 + 95 + 137 + + + 255 + 255 + 255 + + + + + + caption + QDM + + + QLabel + + name + label_logo + + + geometry + + 10 + 10 + 100 + 33 + + + + palette + + + + 0 + 0 + 0 + + + 220 + 220 + 220 + + + 255 + 255 + 255 + + + 237 + 237 + 237 + + + 110 + 110 + 110 + + + 146 + 146 + 146 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 84 + 112 + 152 + + + 255 + 255 + 255 + + + + + 128 + 128 + 128 + + + 220 + 220 + 220 + + + 255 + 255 + 255 + + + 253 + 253 + 253 + + + 110 + 110 + 110 + + + 146 + 146 + 146 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 128 + 128 + 128 + + + 255 + 255 + 255 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 84 + 112 + 152 + + + 255 + 255 + 255 + + + + + 0 + 0 + 0 + + + 220 + 220 + 220 + + + 255 + 255 + 255 + + + 253 + 253 + 253 + + + 110 + 110 + 110 + + + 146 + 146 + 146 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 255 + 255 + 255 + + + 255 + 255 + 255 + + + 0 + 0 + 0 + + + 84 + 112 + 152 + + + 255 + 255 + 255 + + + + + + frameShape + Panel + + + frameShadow + Sunken + + + margin + 2 + + + pixmap + image0 + + + scaledContents + true + + + + QLabel + + name + label_welcome + + + geometry + + 120 + 10 + 110 + 40 + + + + font + + 14 + 1 + + + + text + Welcome to +mLinux [iPAQ] + + + alignment + AlignCenter + + + hAlign + + + + QLabel + + name + label_time + + + geometry + + 180 + 50 + 50 + 16 + + + + text + 12:30:88 + + + + QLabel + + name + label_date + + + geometry + + 70 + 50 + 100 + 16 + + + + text + Wed Feb 12 2001 + + + + QLabel + + name + TextLabel5 + + + geometry + + 20 + 50 + 50 + 16 + + + + text + Today: + + + + QGroupBox + + name + GroupBox3 + + + geometry + + 10 + 80 + 220 + 120 + + + + backgroundOrigin + WidgetOrigin + + + title + Login + + + QPushButton + + name + PushButton3 + + + geometry + + 160 + 60 + 50 + 21 + + + + text + Clear + + + + QLineEdit + + name + input_password + + + geometry + + 80 + 60 + 70 + 22 + + + + echoMode + Password + + + + QComboBox + + name + input_user + + + geometry + + 80 + 30 + 120 + 21 + + + + editable + true + + + + QLabel + + name + label_user + + + geometry + + 10 + 30 + 60 + 21 + + + + text + User + + + + QLabel + + name + label_password + + + geometry + + 10 + 60 + 60 + 21 + + + + text + Password + + + + QPushButton + + name + button_shutdown + + + geometry + + 150 + 90 + 61 + 20 + + + + text + Shutdown + + + + QPushButton + + name + button_login + + + geometry + + 10 + 90 + 60 + 20 + + + + text + Login + + + + QPushButton + + name + button_sleep + + + geometry + + 90 + 90 + 60 + 20 + + + + text + Sleep + + + + + + + image0 + 789ced97db72e2461086effd149475e74a69413258d4d65ef880c7c022cbd8eb35a472a123c8465a09640ebb9577cffc3d033a986c2a38a9ca45bacb653ecd34bf7aba67843e9cd49eac41ede4c3d122b3b3d0adb9537b5e3bf15ea368f3eb6f9f7e1c1db78d9adea8358d5ae3f897a3e3b8e6d6943a19302234e04005d8a8c3811ea10107da40ad01073e123a70e01d502703ce086d38f00bf0b401075e13da70e03760b30e070e086d38d001b6c8804be059130e4c091d3850071aa770a04fe8c2817d609b0ca801e92e68b24be8c18109d0d1e1c021a10f07f6806e130e3409c98016d03b8303c784011c3802fa677020230ce0c00c180486236a3495e8d7697228b0ad891a2d24b6448d3a126d8d4637123d8d6227026d4dd7806b894d51a3ae44e39462eb12bd535ad82b8981a8d1ad40476b52facf129b4d4abf21d168d1d27d97e8b668f446627046a35f05ba4d83bef95262dba01a9d4b740c2aca834457543010e8e96d2aca85c49628e8ab44dba6d1cf123d87eef945a0df10057d92d87269ade612db2e15e55ea2e7d13aaf24061e65a40a84112ab6eda87bcdb56dcf7f7335984c4361cf2f7bc3669ee7450526152f8ebfed5749f8505ab9369f2cb29d2d16af7bee4d89e3385abe4765b5ceb2e9e6fbf9457079d509b3cefc6dd435d788638fbd43e5669a65dd95848bcd9e25eb7971348b62a5ff0e950d5fa6cffb674b1bc4b16df2c0d92e99bfafd2c9b2f0fc6722a68d1887af9a7bb8ca33af79e7767f6fed52b154247377b8ca4af4d6e6ea72bf125219f0ff335effe1c12aeafd3adc7671f781bd097178dd4d84f276fe72b88aaabedc4c3a62cf848b6a428c7ff98c3e3cc6b1d27b870ab7d5ebd76e678a849eca0383288eae53d82c4fe6501552bac1d2754bd746d8f6b945e377abf0038dcb2c56c52bbe1247b9c5b1f30fa8acaa2aa3bb387eb4c6c212de6ddef8309555a110975c655d4d253fc3f9ce11c96c55664369bdbf529984f5877bfa346ff0460b8ba70df555dedc431efd382ea8283bb37eae82c332ec7436ddee063db6b9280e6acab612c2f8ce8cd2ad4ab12f9471316ca8545556b761b87db84c17f5f2b9cf0b1115ef52930f0052d1d3dcfaa530b65c2e476ac59ece9fd793ce66520f569591beae27a5707e41dfe6f2afdbff2aff61959ee627f96e1ca2977b79439baeef0e775b2d11b64546c472a4e042a3b1c4d7127ab970993ada3da35553676a2f3f26923e53597e245896e5f0bf1d02ac9d8a95a64c1debf9ce64a9a53293de6892f2132fe98fd3fc8ad6af3e0f8bbbbbaae2f3347d96cf182db7270c73fda55f3cbfb4e24ee4292ffdd25e2bab9456ccf2d5d44d8a33cc7e2a5e4048332d9c2c56f5a731f387052aab9426f2486bc9d4caaf6eaa8b6f614159696e6eaec9573a35ff54a5b262951963de378c5e01ccc42f97861597cfc268f9a02e4eadf458af32830d355feb1dfffef1e80f6ca1ac19 + + + + + button_shutdown + clicked() + QDMDialog + slot_shutdown() + + + button_login + clicked() + QDMDialog + slot_login() + + + input_password + returnPressed() + button_login + setFocus() + + + input_user + highlighted(const QString&) + input_password + setFocus() + + + PushButton3 + clicked() + input_password + clear() + + + button_sleep + clicked() + QDMDialog + slot_sleepmode() + + slot_sleepmode() + slot_login() + slot_shutdown() + + + input_user + input_password + button_login + PushButton3 + button_sleep + button_shutdown + + diff --git a/core/opie-login/qdmdialogimpl.cpp b/core/opie-login/qdmdialogimpl.cpp new file mode 100644 index 0000000..bb1b453 --- a/dev/null +++ b/core/opie-login/qdmdialogimpl.cpp @@ -0,0 +1,535 @@ +/********************************************************************** +** Copyright (C) 2001 LISA Systems +** +** This file is an additional part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** For further information contact info@lisa.de +** +**********************************************************************/ + +/* + * AUTHOR: Christian Rahn + * EMAIL: cdr@lisa.de + * + * $Id$ + */ + +#include "qdm_config.h" + +#ifdef QT_QWS_LOGIN + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#if defined(QT_QWS_LOGIN_USEPAM) +extern "C" { +#include +} +#else +#define _XOPEN_SOURCE +#include +#include +#endif + + +#include "qdmdialogimpl.h" +#include "../taskbar/inputmethods.h" + + +//---------------------------------------------------------------------------- + +//-- taken from semctl man page +#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) +//-- union semun is defined by including +#else +//-- according to X/OPEN we have to define it ourselves +union semun { + int val; // value for SETVAL + struct semid_ds *buf; // buffer for IPC_STAT, IPC_SET + unsigned short int *array; // array for GETALL, SETALL + struct seminfo *__buf; // buffer for IPC_INFO +}; +#endif + +//---------------------------------------------------------------------------- + +static const int ShowClockFreq = 1; + +QDM_SHOWNUSERS; + +#ifdef QT_QWS_LOGIN_USEPAM + +static const char *_PAM_SERVICE = "xdm"; +static const char *PAM_password; + +typedef const struct pam_message pam_message_type; + +static int PAM_conv( int, pam_message_type **, struct pam_response **, void * ); + +static struct pam_conv PAM_conversation = { + &PAM_conv, + NULL +}; + +//---------------------------------------------------------------------------- + +static char *COPY_STRING( const char * s ) { + return (s) ? strdup(s) : (char *)NULL; +} + +#define GET_MEM if (reply) realloc(reply, size);\ + else reply = (struct pam_response *)malloc(size); \ + if (!reply) return PAM_CONV_ERR; \ + size += sizeof(struct pam_response) + + +static int PAM_conv( int num_msg, pam_message_type **msg, + struct pam_response **resp, void *) +{ + int count = 0, replies = 0; + struct pam_response *reply = NULL; + int size = sizeof(struct pam_response); + + for( count = 0; count < num_msg; count++ ) { + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: + /* user name given to PAM already */ + return PAM_CONV_ERR; + + case PAM_PROMPT_ECHO_OFF: + /* wants password */ + GET_MEM; + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = COPY_STRING(PAM_password); + replies++; + /* PAM frees resp */ + break; + case PAM_TEXT_INFO: + break; + default: + /* unknown or PAM_ERROR_MSG */ + if (reply) free (reply); + return PAM_CONV_ERR; + } + } + if (reply) *resp = reply; + return PAM_SUCCESS; +} + +#endif + + +//---------------------------------------------------------------------------- + +QDMDialogImpl::QDMDialogImpl( QWidget* parent, const char* name, bool modal, WFlags f ) + : QDMDialog( parent, name, modal, f ) +{ + showTime(); + clockTimer = startTimer( ShowClockFreq * 1000 ); //-- call timer evry min. + setActiveWindow(); + setFocus(); + + input = new InputMethods( this ); + input->resize( input->sizeHint() ); + input->move( 0, height() - input->height() ); + + for( int i=0; Shown_Users[i]; ++i ) { + input_user->insertItem( Shown_Users[i] ); + } + input_user->clearEdit(); + + label_welcome->setText( QDM_WELCOME_STRING ); + +}; + + + +QDMDialogImpl::~QDMDialogImpl() +{ + input->lower(); + input->close( false ); + input->hide(); + delete input; + input = 0; + if( parent() ) { + ((QWidget*)parent())->repaint(true); + } +}; + + +void QDMDialogImpl::accept () { }; +void QDMDialogImpl::reject () { }; + + +void QDMDialogImpl::showTime( void ) +{ + label_date->setText( QDate::currentDate().toString() ); + label_time->setText( QTime::currentTime().toString() ); +} + + +void QDMDialogImpl::timerEvent( QTimerEvent * e ) +{ + if( e->timerId() == clockTimer ) + showTime(); +} + + +//---------------------------------------------------------------------------- + +void QDMDialogImpl::slot_sleepmode() +{ + const int button = QMessageBox::warning( this, "Shutdown", tr( "Do you really want to go\nto sleep mode now?" ), + QString::null, tr( "Cancel" ), QString::null,0,1 ); + switch( button ) { + case 0: + done( Rejected ); + // Global::execute( cmd_shutdown ); + if( vfork() == 0 ) { + execl( QDM_CMD_SLEEP, 0 ); + cerr << "Sleepmode: " << strerror( errno ) << endl; + } + break; + + default: + break; + } +} + + +//---------------------------------------------------------------------------- + +void QDMDialogImpl::slot_shutdown() +{ + const int button = QMessageBox::warning( this, "Shutdown", tr("Do you really want to shut\nthe system down now?"), + QString::null, tr("Cancel"), QString::null,0,1 ); + switch( button ) { + case 0: + done( Rejected ); + // Global::execute( cmd_shutdown ); + if( vfork() == 0 ) { + execl( QDM_CMD_SHUTDOWN, 0 ); + cerr << "Shutdown: " << strerror( errno ) << endl; + } + break; + + default: + break; + } +} + + + + +//---------------------------------------------------------------------------- + +void QDMDialogImpl::informBadPassword() +{ + QMessageBox::warning( this, tr("Password wrong"), + tr("The given password is incorrect") ); +} + + +//---------------------------------------------------------------------------- + +#if defined(QT_QWS_LOGIN_USEPAM) + +static bool pwcheck_PAM( const char *user, const char *password ) +{ + bool pw_correct = false; + int pam_error; + int pam_return = 0; + pam_handle_t *pamh = 0; + PAM_password = password.latin1(); + + pam_error = pam_start( _PAM_SERVICE, user, &PAM_conversation, &pamh ); + if( pam_error == PAM_SUCCESS ) { + pam_error = pam_authenticate( pamh, 0 ); + if( pam_error == PAM_SUCCESS ) { + //-- password correct + pw_correct = true; + pam_return = PAM_SUCCESS; + } else { + pam_return = pam_error; + } + } else { + // cerr << "PAM error: " << pam_strerror( pamh, pam_error ) << endl; + } + pam_end( pamh, pam_return ); + return pw_correct; +} + +#else + +//---------------------------------------------------------------------------- + +static bool pwcheck_Unix( const char *user, const char *password ) +{ + struct passwd * pword = getpwnam( user ); + if( pword ) { + if( strcmp( crypt(password, password), pword->pw_passwd) == 0 ) { + return true; + } + } + return false; +} + +#endif + + + +//---------------------------------------------------------------------------- + +void QDMDialogImpl::slot_login() +{ + bool pw_correct = false; + const char *username = input_user->currentText().latin1(); + const char *password = input_password->text().latin1(); + + assert( username ); + +#if defined(QT_QWS_LOGIN_USEPAM) + pw_correct = pwcheck_PAM( username, password ); +#else + pw_correct = pwcheck_Unix( username, password ); +#endif + + if( pw_correct ) { + if( changePersona( username ) ) { + // cerr << "Password correct" << endl; + done( Accepted ); + return; + } + } else { + // cerr << "Password incorrect" << endl; + } + informBadPassword(); +} + + +//---------------------------------------------------------------------------- + +bool QDMDialogImpl::changePersona( const char *username ) +{ + int err; + + //-- get some info on user + struct passwd * pword; + pword = getpwnam( username ); + + if( pword == 0 ) + return false; + + gid_t gid = pword->pw_gid; + uid_t uid = pword->pw_uid; + + //-- some very dirty hacks following + // extern int qws_display_id; + extern QString qws_qtePipeFilename(); + extern QString qws_dataDir(); + + + const QString QTEdataDir = qws_dataDir(); + QString QTEdataDirNew = QTEdataDir; + QTEdataDirNew.replace( QRegExp("root"), username ); + + const char *qws_display_str = getenv("QWS_DISPLAY"); + + //-- get name of semaphore and lock + QString pipe = qws_qtePipeFilename(); + + //-- change owner of semaphore + key_t semkey = ftok( pipe.latin1(), 'd' ); + int semid = semget( semkey, 0, 0 ); + if( semid < 0 ) + cerr << "error: semget, " << strerror( errno ) << endl; + + struct shmid_ds shminfo; + semun arg; + semid_ds semidds; + arg.buf = & semidds; + + if( semctl( semid, 0, IPC_STAT, arg ) < 0 ) + cerr << "error: semctl stat, " << strerror( errno ) << endl; + + arg.buf->sem_perm.uid = uid; + arg.buf->sem_perm.gid = gid; + + if( semctl( semid, 0, IPC_SET, arg ) < 0 ) + cerr << "error: semctl set, " << strerror( errno ) << endl; + + //-- change owner of shared memory + key_t memkey = ftok( pipe.latin1(), 'm' ); + int ramid = shmget( memkey, 0, 0 ); + if( ramid < 0 ) cerr << "error: shmget, " << strerror( errno ) << endl; + + if( shmctl( ramid, IPC_STAT, &shminfo ) < 0 ) + cerr << "error: shmctl stat, " << strerror( errno ) << endl; + + shminfo.shm_perm.uid = uid; + shminfo.shm_perm.gid = gid; + + if( shmctl( ramid, IPC_SET, &shminfo ) < 0 ) + cerr << "error: shmctl set, " << strerror( errno ) << endl; + + //-- change owner of region manager + memkey = ftok( pipe.latin1(), 'r' ); + int regionid = shmget( memkey, 0, 0 ); + if( regionid < 0 ) + cerr << "error: shmget, " << strerror( errno ) << endl; + + if( shmctl( regionid, IPC_STAT, &shminfo ) < 0 ) + cerr << "error: shmctl stat, " << strerror( errno ) << endl; + + shminfo.shm_perm.uid = uid; + shminfo.shm_perm.gid = gid; + + if( shmctl( regionid, IPC_SET, &shminfo ) < 0 ) + cerr << "error: shmctl set, " << strerror( errno ) << endl; + + // cerr << "ungrabbing qws display: " << qws_display_id << " on lock " << pipe << endl; + // QWSDisplay::ungrab(); + + //-- presenting socket-file to new user + chown( pipe.latin1(), uid, gid ); + chown( QTEdataDir.latin1(), uid, gid ); + + + //-- another dirty hack - force framebuffer to be writeable... + struct stat devstat; + if( ! stat( "/dev/fb0", &devstat ) ) { + if( chmod( "/dev/fb0", devstat.st_mode |S_IWOTH |S_IWUSR |S_IWGRP ) ) { + cerr << "chmod error: " << strerror( errno ) << endl; + } + } + + err = rename( QTEdataDir, QTEdataDirNew ) ; + if( err < 0 ) cerr << "error: rename " << strerror(errno) + << " , " << QTEdataDir << " -> " << QTEdataDirNew << endl; + + // + //-- actually change uid and gid + // + // cerr << "changing persona, uid: " << uid << " gid: " << gid << endl; + + err = setgid( gid ); + if( err != 0 ) cerr << "error: gid changePersona " << err << endl; + + err = setuid( uid ); + if( err != 0 ) cerr << "error: uid changePersona " << err << endl; + + + //-- set some environment + setenv( "QWS_DISPLAY", qws_display_str, true ); + setenv( "LOGNAME", username, true ); + setenv( "USER", username, true ); + setenv( "HOME", pword->pw_dir, true ); + + // cout << "QTE data dir: " << qws_dataDir() << endl; + + //-- I am reborn + + return true; +} + + + +//---------------------------------------------------------------------------- + +bool QDMDialogImpl::login( QWidget *parent ) +{ + //-- only when called as 'root' do login-box + if( getuid() != 0 ) + return true; + + + //-- are we coming from a 'restart' ? + if( getenv("QDM_STARTED") ) + return true; + else + unsetenv("QDM_STARTED"); + + +#ifndef QT_NO_TRANSLATION + QString lang = getenv( "LANG" ); + + QTranslator * trans = new QTranslator(qApp); + QString tfn = QPEApplication::qpeDir()+"/i18n/"+lang+"/login.qm"; + if ( trans->load( tfn )) + qApp->installTranslator( trans ); + else { + delete trans; + trans = 0; + } +#endif + + if( parent ) parent->erase(); + + QDMDialog *dialog = new QDMDialogImpl( parent, "Login", true //); + ,WStyle_NoBorder | WStyle_Customize ); + +#if QT_VERSION >= 300 + Q_CHECK_PTR( dialog ); +#else + CHECK_PTR( dialog ); +#endif + int result = dialog->exec(); + delete dialog; + + if( parent ) parent->erase(); + +#ifndef QT_NO_TRANSLATION + if( trans ) { + qApp->removeTranslator( trans ); + delete trans; + trans = 0; + } +#endif + + setenv( "QDM_STARTED", "", true ); + + // if( parent ) parent->erase(); + + //-- get all configs going + Global::restart(); + + return result; +} + + +#endif //-- QT_QWS_LOGIN diff --git a/core/opie-login/qdmdialogimpl.h b/core/opie-login/qdmdialogimpl.h new file mode 100644 index 0000000..d62695b --- a/dev/null +++ b/core/opie-login/qdmdialogimpl.h @@ -0,0 +1,90 @@ +//-- -*- c++ -*- +/********************************************************************** +** Copyright (C) 2001 LISA Systems +** +** This file is an additional part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** For further information contact info@lisa.de +** +**********************************************************************/ + +/* + * AUTHOR: Christian Rahn + * EMAIL: cdr@lisa.de + * + * $Id$ + */ + +#ifndef _QDM_IMPL_H +#define _QDM_IMPL_H + +#include "qdm_config.h" + +#if defined(QT_QWS_LOGIN) + +#include "qdmdialog.h" + +class InputMethods; + +class QDMDialogImpl : public QDMDialog +{ + Q_OBJECT + + public: + /** Pop up login dialog and do all stuff */ + static bool login( QWidget * parent = 0 ); + + protected: + /** a protected constructor */ + QDMDialogImpl( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags f = 0 ); + ~QDMDialogImpl(); + + /** Timer for clock display */ + void timerEvent( QTimerEvent * ); + + /** The Timer for the clock */ + int clockTimer; + + /** Conersation function for PAM */ + // int PAM_conv (int num_msg, pam_message_type **msg, struct pam_response **resp, void *); + + /** Just become (i.e. log in as) user */ + bool changePersona( const char *name ); + + /** Inform about an incorrect given password */ + void informBadPassword(); + +private: + InputMethods *input; + + protected slots: + /** These got to be overridden so that the login dialog can't be circumvented */ + virtual void accept (); + virtual void reject (); + +public slots: + /** Display the atual time and date */ + void showTime( void ); + + /** login button pressed */ + virtual void slot_login(); + + /** Shutdown button pressed */ + virtual void slot_shutdown(); + + /** Sleep button pressed */ + virtual void slot_sleepmode(); +}; + +#endif //-- QT_QWS_LOGIN + +#endif //-- _QDM_IMPL_H + diff --git a/core/pim/addressbook/.cvsignore b/core/pim/addressbook/.cvsignore new file mode 100644 index 0000000..28d87f2 --- a/dev/null +++ b/core/pim/addressbook/.cvsignore @@ -0,0 +1,16 @@ +moc_* +Makefile +abeditorbase.h +abaddress.h +abcompanybase.h +abnamebase.h +abeditorbase.cpp +abaddress.cpp +abcompanybase.cpp +abnamebase.cpp +abeditorpage2base.ui +abeditorpage2base.h +abeditorpage2base.cpp +addresssettingsbase.h +addresssettingsbase.cpp + diff --git a/core/pim/addressbook/Makefile.in b/core/pim/addressbook/Makefile.in new file mode 100644 index 0000000..93c73c3 --- a/dev/null +++ b/core/pim/addressbook/Makefile.in @@ -0,0 +1,244 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = $(QPEDIR)/bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = addressbook +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = addressbook.h \ + abeditor.h \ + ablabel.h \ + abtable.h \ + addresssettings.h +SOURCES = main.cpp \ + addressbook.cpp \ + abeditor.cpp \ + ablabel.cpp \ + abtable.cpp \ + addresssettings.cpp +OBJECTS = main.o \ + addressbook.o \ + abeditor.o \ + ablabel.o \ + abtable.o \ + addresssettings.o \ + addresssettingsbase.o +INTERFACES = addresssettingsbase.ui +UICDECLS = addresssettingsbase.h +UICIMPLS = addresssettingsbase.cpp +SRCMOC = moc_addressbook.cpp \ + moc_abeditor.cpp \ + moc_ablabel.cpp \ + moc_abtable.cpp \ + moc_addresssettings.cpp \ + moc_addresssettingsbase.cpp +OBJMOC = moc_addressbook.o \ + moc_abeditor.o \ + moc_ablabel.o \ + moc_abtable.o \ + moc_addresssettings.o \ + moc_addresssettingsbase.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake p4addressbook.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +main.o: main.cpp \ + addressbook.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h + +addressbook.o: addressbook.cpp \ + abeditor.h \ + $(QPEDIR)/include/qpe/contact.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/recordfields.h \ + ablabel.h \ + abtable.h \ + $(QPEDIR)/include/qpe/categories.h \ + addresssettings.h \ + addresssettingsbase.h \ + addressbook.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/finddialog.h \ + $(QPEDIR)/include/qpe/global.h \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/ir.h \ + $(QPEDIR)/include/qpe/qpemessagebox.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h \ + $(QPEDIR)/include/qpe/qpemenubar.h \ + $(QPEDIR)/include/qpe/qpetoolbar.h + +abeditor.o: abeditor.cpp \ + abeditor.h \ + $(QPEDIR)/include/qpe/contact.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/recordfields.h \ + addresspicker.h \ + $(QPEDIR)/include/qpe/categoryselect.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/qpedialog.h + +ablabel.o: ablabel.cpp \ + ablabel.h \ + $(QPEDIR)/include/qpe/contact.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/recordfields.h \ + $(QPEDIR)/include/qpe/stringutil.h + +abtable.o: abtable.cpp \ + $(QPEDIR)/include/qpe/categoryselect.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/stringutil.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h \ + abtable.h \ + $(QPEDIR)/include/qpe/categories.h \ + $(QPEDIR)/include/qpe/contact.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/recordfields.h + +addresssettings.o: addresssettings.cpp \ + addresssettings.h \ + addresssettingsbase.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/contact.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/recordfields.h + +addresssettingsbase.h: addresssettingsbase.ui + $(UIC) addresssettingsbase.ui -o $(INTERFACE_DECL_PATH)/addresssettingsbase.h + +addresssettingsbase.cpp: addresssettingsbase.ui + $(UIC) addresssettingsbase.ui -i addresssettingsbase.h -o addresssettingsbase.cpp + +addresssettingsbase.o: addresssettingsbase.cpp \ + addresssettingsbase.h \ + addresssettingsbase.ui + +moc_addressbook.o: moc_addressbook.cpp \ + addressbook.h + +moc_abeditor.o: moc_abeditor.cpp \ + abeditor.h \ + $(QPEDIR)/include/qpe/contact.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/recordfields.h + +moc_ablabel.o: moc_ablabel.cpp \ + ablabel.h \ + $(QPEDIR)/include/qpe/contact.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/recordfields.h + +moc_abtable.o: moc_abtable.cpp \ + abtable.h \ + $(QPEDIR)/include/qpe/categories.h \ + $(QPEDIR)/include/qpe/contact.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/recordfields.h + +moc_addresssettings.o: moc_addresssettings.cpp \ + addresssettings.h \ + addresssettingsbase.h + +moc_addresssettingsbase.o: moc_addresssettingsbase.cpp \ + addresssettingsbase.h + +moc_addressbook.cpp: addressbook.h + $(MOC) addressbook.h -o moc_addressbook.cpp + +moc_abeditor.cpp: abeditor.h + $(MOC) abeditor.h -o moc_abeditor.cpp + +moc_ablabel.cpp: ablabel.h + $(MOC) ablabel.h -o moc_ablabel.cpp + +moc_abtable.cpp: abtable.h + $(MOC) abtable.h -o moc_abtable.cpp + +moc_addresssettings.cpp: addresssettings.h + $(MOC) addresssettings.h -o moc_addresssettings.cpp + +moc_addresssettingsbase.cpp: addresssettingsbase.h + $(MOC) addresssettingsbase.h -o moc_addresssettingsbase.cpp + + diff --git a/core/pim/addressbook/abeditor.cpp b/core/pim/addressbook/abeditor.cpp new file mode 100644 index 0000000..6354db9 --- a/dev/null +++ b/core/pim/addressbook/abeditor.cpp @@ -0,0 +1,619 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "abeditor.h" +#include "addresspicker.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static inline bool containsAlphaNum( const QString &str ); +static inline bool constainsWhiteSpace( const QString &str ); + + +// helper functions, convert our comma delimited list to proper +// file format... +void parseEmailFrom( const QString &txt, QString &strDefaultEmail, + QString &strAll ); + +// helper convert from file format to comma delimited... +void parseEmailTo( const QString &strDefaultEmail, + const QString &strOtherEmail, QString &strBack ); + + + +AbEditor::AbEditor( const Contact &entry, const QValueList *newOrdered, + QStringList *slNewOrdered, + QWidget *parent = 0, const char *name = 0, WFlags fl = 0 ) + : QDialog( parent, name, TRUE, fl ), + orderedValues( newOrdered ), + slOrdered( slNewOrdered ) +{ + init(); + initMap(); + setEntry( entry ); +} + +AbEditor::~AbEditor() +{ +} + +void AbEditor::init() +{ + middleEdit = 0; + QVBoxLayout *vb = new QVBoxLayout( this ); + svPage = new QScrollView( this ); + svPage->setHScrollBarMode( QScrollView::AlwaysOff ); + vb->addWidget( svPage ); + svPage->setResizePolicy( QScrollView::AutoOneFit ); + svPage->setFrameStyle( QFrame::NoFrame ); + + QWidget *container = new QWidget( svPage->viewport() ); + svPage->addChild( container ); + + QGridLayout *gl = new QGridLayout( container, 20, 2, 4, 2 ); + + QLabel *l = new QLabel( tr("First Name"), container ); + gl->addWidget( l, 0, 0 ); + firstEdit = new QLineEdit( container ); + gl->addWidget( firstEdit, 0, 1 ); + + l = new QLabel( tr("Last Name"), container ); + gl->addWidget( l, 1, 0 ); + lastEdit = new QLineEdit( container ); + gl->addWidget( lastEdit, 1, 1 ); + + l = new QLabel( tr("Categories"), container ); + gl->addWidget( l, 2, 0 ); + + cmbCat = new CategorySelect( container ); + gl->addWidget( cmbCat, 2, 1 ); + + int i; + bool foundGender, + foundNotes; + foundGender = foundNotes = false; + QStringList::ConstIterator it = slOrdered->begin(); + for ( i = 0; it != slOrdered->end(); i++, ++it ) { + if ( !foundGender && *it == tr("Gender") ) { + foundGender = true; + } else if ( !foundNotes && *it == tr("Notes") ) { + foundNotes = true; + } else { + l = new QLabel( *it, container ); + listName.append( l ); + gl->addWidget( l, i + 3, 0 ); + QLineEdit *e = new QLineEdit( container ); + listValue.append( e ); + gl->addWidget( e, i + 3, 1 ); + if ( *it == tr( "Middle Name" ) ) + middleEdit = e; + } + } + l = new QLabel( tr("Gender"), container ); + gl->addWidget( l, slOrdered->count() + 3, 0 ); + genderCombo = new QComboBox( container ); + genderCombo->insertItem( "", 0 ); + genderCombo->insertItem( tr( "Male" ), 1 ); + genderCombo->insertItem( tr( "Female" ), 2 ); + gl->addWidget( genderCombo, slOrdered->count() + 3, 1 ); + + dlgNote = new QDialog( this, "Note Dialog", TRUE ); + dlgNote->setCaption( tr("Enter Note") ); + QVBoxLayout *vbNote = new QVBoxLayout( dlgNote ); + // lblNote = new QLabel( dlgNote ); + // lblNote->setMinimumSize( lblNote->sizeHint() + QSize( 0, 4 ) ); + // vbNote->addWidget( lblNote ); + txtNote = new QMultiLineEdit( dlgNote ); + vbNote->addWidget( txtNote ); + + QHBoxLayout *hb = new QHBoxLayout( vb ); + hb->addStretch( 2 ); + QPushButton *pb = new QPushButton( tr("Notes..."), this ); + hb->addWidget( pb ); + connect( pb, SIGNAL(clicked()), this, SLOT(slotNote()) ); + + new QPEDialogListener(this); +} + +void AbEditor::initMap() +{ + /* + // since the fields and the XML fields exist, create a map + // between them... + Config cfg1( "AddressBook" ); + Config cfg2( "AddressBook" ); + QString strCfg1, + strCfg2; + int i; + + // This stuff better exist... + cfg1.setGroup( "AddressFields" ); + cfg2.setGroup( "XMLFields" ); + i = 0; + strCfg1 = cfg1.readEntry( "Field" + QString::number(i), QString::null ); + strCfg2 = cfg2.readEntry( "XMLField" + QString::number(i++), + QString::null ); + while ( !strCfg1.isNull() && !strCfg2.isNull() ) { + mapField.insert( strCfg1, strCfg2 ); + strCfg1 = cfg1.readEntry( "Field" + QString::number(i), + QString::null ); + strCfg2 = cfg2.readEntry( "XMLField" + QString::number(i++), + QString::null ); + } + */ +} + +void AbEditor::loadFields() +{ + QStringList::ConstIterator it; + QListIterator lit( listName ); + for ( it = slOrdered->begin(); *lit; ++lit, ++it ) { + (*lit)->setText( *it ); + } +} + +void AbEditor::setEntry( const Contact &entry ) +{ + ent = entry; + QListIterator it( listValue ); + firstEdit->setText( ent.firstName() ); + lastEdit->setText( ent.lastName() ); + cmbCat->setCategories( ent.categories(), "Contacts", tr("Contacts") ); + + // ### Fix... + QValueList::ConstIterator itVl; + for ( itVl = orderedValues->begin(); *it && itVl != orderedValues->end(); + ++itVl, ++it ) { + switch( *itVl ) { + case Qtopia::Title: + (*it)->setText(ent.title()); + break; + case Qtopia::MiddleName: + (*it)->setText( ent.middleName() ); + break; + case Qtopia::Suffix: + (*it)->setText( ent.suffix() ); + break; + + // email + case Qtopia::DefaultEmail: + case Qtopia::Emails: + { + QString strDefEmail = ent.defaultEmail(); + QString strAllEmail = ent.emails(); + QString strFinal; + parseEmailTo( strDefEmail, strAllEmail, strFinal ); + (*it)->setText( strFinal ); + // make sure we see the "default" + (*it)->home( false ); + break; + } + + // home + case Qtopia::HomeStreet: + (*it)->setText(ent.homeStreet() ); + break; + case Qtopia::HomeCity: + (*it)->setText( ent.homeCity() ); + break; + case Qtopia::HomeState: + (*it)->setText( ent.homeState() ); + break; + case Qtopia::HomeZip: + (*it)->setText( ent.homeZip() ); + break; + case Qtopia::HomeCountry: + (*it)->setText( ent.homeCountry() ); + break; + case Qtopia::HomePhone: + (*it)->setText( ent.homePhone() ); + break; + case Qtopia::HomeFax: + (*it)->setText( ent.homeFax() ); + break; + case Qtopia::HomeMobile: + (*it)->setText( ent.homeMobile() ); + break; + case Qtopia::HomeWebPage: + (*it)->setText( ent.homeWebpage() ); + break; + + // business + case Qtopia::Company: + (*it)->setText( ent.company() ); + break; + case Qtopia::BusinessStreet: + (*it)->setText( ent.businessStreet() ); + break; + case Qtopia::BusinessCity: + (*it)->setText( ent.businessCity() ); + break; + case Qtopia::BusinessState: + (*it)->setText( ent.businessState() ); + break; + case Qtopia::BusinessZip: + (*it)->setText( ent.businessZip() ); + break; + case Qtopia::BusinessCountry: + (*it)->setText( ent.businessCountry() ); + break; + case Qtopia::BusinessWebPage: + (*it)->setText( ent.businessWebpage() ); + break; + case Qtopia::JobTitle: + (*it)->setText( ent.jobTitle() ); + break; + case Qtopia::Department: + (*it)->setText( ent.department() ); + break; + case Qtopia::Office: + (*it)->setText( ent.office() ); + break; + case Qtopia::BusinessPhone: + (*it)->setText( ent.businessPhone() ); + break; + case Qtopia::BusinessFax: + (*it)->setText( ent.businessFax() ); + break; + case Qtopia::BusinessMobile: + (*it)->setText( ent.businessMobile() ); + break; + case Qtopia::BusinessPager: + (*it)->setText( ent.businessPager() ); + break; + case Qtopia::Profession: + (*it)->setText( ent.profession() ); + break; + case Qtopia::Assistant: + (*it)->setText( ent.assistant() ); + break; + case Qtopia::Manager: + (*it)->setText( ent.manager() ); + break; + + // personal + case Qtopia::Spouse: + (*it)->setText( ent.spouse() ); + break; + case Qtopia::Children: + (*it)->setText( ent.children() ); + break; + case Qtopia::Birthday: + (*it)->setText( ent.birthday() ); + break; + case Qtopia::Anniversary: + (*it)->setText( ent.anniversary() ); + break; + case Qtopia::Nickname: + (*it)->setText( ent.nickname() ); + break; + + } + } + + QString gender = ent.gender(); + genderCombo->setCurrentItem( gender.toInt() ); + + txtNote->setText( ent.notes() ); +} + +void AbEditor::accept() +{ + if ( isEmpty() ) + reject(); + else { + saveEntry(); + QDialog::accept(); + } +} + +bool AbEditor::isEmpty() +{ + // analyze all the fields and make sure there is _something_ there + // that warrants saving... + QString t = firstEdit->text(); + if ( !t.isEmpty() && containsAlphaNum( t ) ) + return false; + + t = lastEdit->text(); + if ( !t.isEmpty() && containsAlphaNum( t ) ) + return false; + + QListIterator it( listValue ); + for ( ; it.current(); ++it ) { + t = it.current()->text(); + if ( !t.isEmpty() && containsAlphaNum( t ) ) + return false; + } + + t = txtNote->text(); + if ( !t.isEmpty() && containsAlphaNum( t ) ) + return false; + + return true; +} + +void AbEditor::saveEntry() +{ + QString strDefaultEmail, strOtherEmail; + + // determine if there has been a change in names + if ( ent.firstName() != firstEdit->text() || + ent.lastName() != lastEdit->text() + || (middleEdit && ent.middleName() != middleEdit->text()) ) { + // set the names + ent.setFirstName( firstEdit->text() ); + ent.setLastName( lastEdit->text() ); + if ( middleEdit ) + ent.setMiddleName( middleEdit->text() ); + ent.setFileAs(); + } + + ent.setCategories( cmbCat->currentCategories() ); + + QListIterator it( listValue ); + int i; + QValueList::ConstIterator vlIt; + for ( i = 0, vlIt = orderedValues->begin(); + it.current(); ++it, ++vlIt, i++ ) { + switch( *vlIt ) { + case Qtopia::Title: + ent.setTitle( it.current()->text() ); + break; + case Qtopia::MiddleName: + ent.setMiddleName( it.current()->text() ); + break; + case Qtopia::Suffix: + ent.setSuffix( it.current()->text() ); + break; +// case Qtopia::Category: +// { +// // QStringList slCat = QStringList::split( ";", value ); +// // QValueList cat; +// // for ( QStringList::ConstIterator it = slCat.begin(); +// // it != slCat.end(); ++it ) +// // cat.append( (*it).toInt() ); +// // ent.setCategories( cat ); +// } +// break; + + // email + case Qtopia::DefaultEmail: + case Qtopia::Emails: + parseEmailFrom( it.current()->text(), strDefaultEmail, + strOtherEmail ); + ent.setDefaultEmail( strDefaultEmail ); + ent.setEmails( strOtherEmail ); + break; + + // home + case Qtopia::HomeStreet: + ent.setHomeStreet( it.current()->text() ); + break; + case Qtopia::HomeCity: + ent.setHomeCity( it.current()->text() ); + break; + case Qtopia::HomeState: + ent.setHomeState( it.current()->text() ); + break; + case Qtopia::HomeZip: + ent.setHomeZip( it.current()->text() ); + break; + case Qtopia::HomeCountry: + ent.setHomeCountry( it.current()->text() ); + break; + case Qtopia::HomePhone: + ent.setHomePhone( it.current()->text() ); + break; + case Qtopia::HomeFax: + ent.setHomeFax( it.current()->text() ); + break; + case Qtopia::HomeMobile: + ent.setHomeMobile( it.current()->text() ); + break; + case Qtopia::HomeWebPage: + ent.setHomeWebpage( it.current()->text() ); + break; + + // business + case Qtopia::Company: + ent.setCompany( it.current()->text() ); + break; + case Qtopia::BusinessStreet: + ent.setBusinessStreet( it.current()->text() ); + break; + case Qtopia::BusinessCity: + ent.setBusinessCity( it.current()->text() ); + break; + case Qtopia::BusinessState: + ent.setBusinessState( it.current()->text() ); + break; + case Qtopia::BusinessZip: + ent.setBusinessZip( it.current()->text() ); + break; + case Qtopia::BusinessCountry: + ent.setBusinessCountry( it.current()->text() ); + break; + case Qtopia::BusinessWebPage: + ent.setBusinessWebpage( it.current()->text() ); + break; + case Qtopia::JobTitle: + ent.setJobTitle( it.current()->text() ); + break; + case Qtopia::Department: + ent.setDepartment( it.current()->text() ); + break; + case Qtopia::Office: + ent.setOffice( it.current()->text() ); + break; + case Qtopia::BusinessPhone: + ent.setBusinessPhone( it.current()->text() ); + break; + case Qtopia::BusinessFax: + ent.setBusinessFax( it.current()->text() ); + break; + case Qtopia::BusinessMobile: + ent.setBusinessMobile( it.current()->text() ); + break; + case Qtopia::BusinessPager: + ent.setBusinessPager( it.current()->text() ); + break; + case Qtopia::Profession: + ent.setProfession( it.current()->text() ); + break; + case Qtopia::Assistant: + ent.setAssistant( it.current()->text() ); + break; + case Qtopia::Manager: + ent.setManager( it.current()->text() ); + break; + + // personal + case Qtopia::Spouse: + ent.setSpouse( it.current()->text() ); + break; + case Qtopia::Children: + ent.setChildren( it.current()->text() ); + break; + case Qtopia::Birthday: + ent.setBirthday( it.current()->text() ); + break; + case Qtopia::Anniversary: + ent.setAnniversary( it.current()->text() ); + break; + case Qtopia::Nickname: + ent.setNickname( it.current()->text() ); + break; + default: + break; + + } + } + + int gender = genderCombo->currentItem(); + ent.setGender( QString::number( gender ) ); + + QString str = txtNote->text(); + if ( !str.isNull() ) + ent.setNotes( str ); +} + +void AbEditor::slotNote() +{ + dlgNote->showMaximized(); + if ( !dlgNote->exec() ) { + // reset the note... + txtNote->setText( ent.notes() ); + } +} + +void AbEditor::setNameFocus() +{ + firstEdit->setFocus(); +} + +void parseEmailFrom( const QString &txt, QString &strDefaultEmail, + QString &strAll ) +{ + int where, + start; + if ( txt.isEmpty() ) + return; + // find the first + where = txt.find( ',' ); + if ( where < 0 ) { + strDefaultEmail = txt; + strAll = txt; + } else { + strDefaultEmail = txt.left( where ).stripWhiteSpace(); + strAll = strDefaultEmail; + while ( where > -1 ) { + strAll.append(" "); + start = where; + where = txt.find( ',', where + 1 ); + if ( where > - 1 ) + strAll.append( txt.mid(start + 1, where - start - 1).stripWhiteSpace() ); + else // grab until the end... + strAll.append( txt.right(txt.length() - start - 1).stripWhiteSpace() ); + } + } +} + +void parseEmailTo( const QString &strDefaultEmail, + const QString &strOtherEmail, QString &strBack ) +{ + // create a comma dilimeted set of emails... + // use the power of short circuiting... + bool foundDefault = false; + QString strTmp; + int start = 0; + int where; + // start at the beginng. + strBack = strDefaultEmail; + where = 0; + while ( where > -1 ) { + start = where; + where = strOtherEmail.find( ' ', where + 1 ); + if ( where > 0 ) { + strTmp = strOtherEmail.mid( start, where - start ).stripWhiteSpace(); + } else + strTmp = strOtherEmail.right( strOtherEmail.length() - start ).stripWhiteSpace(); + if ( foundDefault || strTmp != strDefaultEmail ) { + strBack.append( ", " ); + strBack.append( strTmp ); + } else + foundDefault = true; + } +} + + +static inline bool containsAlphaNum( const QString &str ) +{ + int i, + count = str.length(); + for ( i = 0; i < count; i++ ) + if ( !str[i].isSpace() ) + return TRUE; + return FALSE; +} + +static inline bool constainsWhiteSpace( const QString &str ) +{ + int i, + count = str.length(); + for (i = 0; i < count; i++ ) + if ( str[i].isSpace() ) + return TRUE; + return FALSE; +} + diff --git a/core/pim/addressbook/abeditor.h b/core/pim/addressbook/abeditor.h new file mode 100644 index 0000000..9ce6704 --- a/dev/null +++ b/core/pim/addressbook/abeditor.h @@ -0,0 +1,79 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef ABEDITOR_H +#define ABEDITOR_H + +#include + +#include +#include +#include +#include + +class QScrollView; +class QMultiLineEdit; +class QLineEdit; +class QLabel; +class QComboBox; +class CategorySelect; + +class AbEditor : public QDialog +{ + Q_OBJECT +public: + AbEditor( const Contact &entry, const QValueList *newOrdedValues, + QStringList *slNewOrdered, + QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~AbEditor(); + void loadFields(); + void setNameFocus(); + Contact entry() const { return ent; } + +public slots: + void slotNote(); + void setEntry( const Contact &entry ); + +protected slots: + void accept(); + +private: + void init(); + void initMap(); + void saveEntry(); + bool isEmpty(); + +private: + QDialog *dlgNote; + QLabel *lblNote; + QMultiLineEdit *txtNote; + Contact ent; + QScrollView *svPage; + QLineEdit *firstEdit; + QLineEdit *lastEdit; + QLineEdit *middleEdit; + QComboBox *genderCombo; + QList listValue; + QList listName; + const QValueList *orderedValues; + QStringList *slOrdered; + CategorySelect *cmbCat; +}; + +#endif diff --git a/core/pim/addressbook/ablabel.cpp b/core/pim/addressbook/ablabel.cpp new file mode 100644 index 0000000..3bf3e12 --- a/dev/null +++ b/core/pim/addressbook/ablabel.cpp @@ -0,0 +1,53 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "ablabel.h" + +#include + +#include +#include + +AbLabel::AbLabel( QWidget *parent, const char *name ) + : QTextView( parent, name ) +{ +} + +AbLabel::~AbLabel() +{ +} + +void AbLabel::init( const Contact &entry ) +{ + ent = entry; +} + +void AbLabel::sync() +{ + QString text = ent.toRichText(); + setText( text ); +} + +void AbLabel::keyPressEvent( QKeyEvent *e ) +{ + if ( e->key() == Qt::Key_F33 ) { + emit okPressed(); + } +} diff --git a/core/pim/addressbook/ablabel.h b/core/pim/addressbook/ablabel.h new file mode 100644 index 0000000..cfbd999 --- a/dev/null +++ b/core/pim/addressbook/ablabel.h @@ -0,0 +1,50 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef ABLABEL_H +#define ABLABEL_H + +#include +#include + +class AbLabel : public QTextView +{ + Q_OBJECT + +public: + AbLabel( QWidget *parent, const char *name = 0 ); + ~AbLabel(); + +public slots: + void init( const Contact &entry ); + void sync(); + +signals: + void okPressed(); + +protected: + void keyPressEvent( QKeyEvent * ); + +private: + Contact ent; + +}; + +#endif // ABLABEL_H + diff --git a/core/pim/addressbook/abtable.cpp b/core/pim/addressbook/abtable.cpp new file mode 100644 index 0000000..0911edf --- a/dev/null +++ b/core/pim/addressbook/abtable.cpp @@ -0,0 +1,1091 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include + +#include "abtable.h" + +#include +#include +#include +#include + +#include //toupper() for key hack + +static bool contactCompare( const Contact &cnt, const QRegExp &r, int category ); + +//### qtmail/addresslist.cpp hardcodes this filename as well +static QString journalFileName() +{ + QString str = getenv("HOME"); + str +="/.abjournal"; + return str; +} + + + +/*! + \class AbTableItem abtable.h + + \brief QTableItem based class for showing a field of an entry +*/ + +AbTableItem::AbTableItem( QTable *t, EditType et, const QString &s, + const QString &secondSortKey) + : QTableItem( t, et, s ) +{ + // sortKey = s.lower() + QChar( '\0' ) + secondSortKey.lower(); + sortKey = Qtopia::buildSortKey( s, secondSortKey ); +} + +int AbTableItem::alignment() const +{ + return AlignLeft|AlignVCenter; +} + +QString AbTableItem::key() const +{ + return sortKey; +} + +// A way to reset the item, without out doing a delete or a new... +void AbTableItem::setItem( const QString &txt, const QString &secondKey ) +{ + setText( txt ); + sortKey = Qtopia::buildSortKey( txt, secondKey ); + + // sortKey = txt.lower() + QChar( '\0' ) + secondKey.lower(); +} + +/*! + \class AbPickItem abtable.h + + \brief QTableItem based class for showing slection of an entry +*/ + +AbPickItem::AbPickItem( QTable *t ) : + QTableItem(t, WhenCurrent, "?") +{ +} + +QWidget *AbPickItem::createEditor() const +{ + QComboBox* combo = new QComboBox( table()->viewport() ); + ( (AbPickItem*)this )->cb = combo; + AbTable* t = static_cast(table()); + QStringList c = t->choiceNames(); + int cur = 0; + for (QStringList::ConstIterator it = c.begin(); it!=c.end(); ++it) { + if ( *it == text() ) + cur = combo->count(); + combo->insertItem(*it); + } + combo->setCurrentItem(cur); + return combo; +} + +void AbPickItem::setContentFromEditor( QWidget *w ) +{ + if ( w->inherits("QComboBox") ) + setText( ( (QComboBox*)w )->currentText() ); + else + QTableItem::setContentFromEditor( w ); +} + +/*! + \class AbTable abtable.h + + \brief QTable based class for showing a list of entries +*/ + +AbTable::AbTable( const QValueList *order, QWidget *parent, const char *name ) +// #ifdef QT_QTABLE_NOHEADER_CONSTRUCTOR +// : QTable( 0, 0, parent, name, TRUE ), +// #else + : QTable( parent, name ), +// #endif + lastSortCol( -1 ), + asc( TRUE ), + intFields( order ), + currFindRow( -2 ), + mCat( 0 ) +{ + mCat.load( categoryFileName() ); + setSelectionMode( NoSelection ); + init(); + setSorting( TRUE ); + connect( this, SIGNAL(clicked(int,int,int,const QPoint &)), + this, SLOT(itemClicked(int,int)) ); +} + +AbTable::~AbTable() +{ +} + +void AbTable::init() +{ + setNumRows( 0 ); + setNumCols( 2 ); + + horizontalHeader()->setLabel( 0, tr( "Full Name" )); + horizontalHeader()->setLabel( 1, tr( "Contact" )); + setLeftMargin( 0 ); + verticalHeader()->hide(); +} + +void AbTable::columnClicked( int col ) +{ + if ( !sorting() ) + return; + + if ( lastSortCol == -1 ) + lastSortCol = col; + + if ( col == lastSortCol ) { + asc = !asc; + } else { + lastSortCol = col; + asc = TRUE; + } + resort(); +} + +void AbTable::resort() +{ + if ( sorting() ) { + if ( lastSortCol == -1 ) + lastSortCol = 0; + sortColumn( lastSortCol, asc, TRUE ); + updateVisible(); + } +} + +Contact AbTable::currentEntry() +{ + Contact cnt; + AbTableItem *abItem; + abItem = static_cast(item( currentRow(), 0 )); + if ( abItem ) { + cnt = contactList[abItem]; + } + return cnt; +} + +void AbTable::replaceCurrentEntry( const Contact &newContact ) +{ + int row = currentRow(); + updateJournal( newContact, Contact::ACTION_REPLACE, row ); + updateVisible(); + + journalFreeReplace( newContact, row ); +} + +void AbTable::deleteCurrentEntry() +{ + int row = currentRow(); + AbTableItem *abItem; + abItem = static_cast(item( row, 0 )); + Contact oldContact; + oldContact = contactList[abItem]; + updateJournal( oldContact, Contact::ACTION_REMOVE, row ); + + // a little wasteful, but it ensure's there is only one place + // where we delete. + journalFreeRemove( row ); + updateVisible(); + + if ( numRows() == 0 ) + emit empty( TRUE ); +} + +void AbTable::clear() +{ + contactList.clear(); + for ( int r = 0; r < numRows(); ++r ) { + for ( int c = 0; c < numCols(); ++c ) { + if ( cellWidget( r, c ) ) + clearCellWidget( r, c ); + clearCell( r, c ); + } + } + setNumRows( 0 ); +} + +void AbTable::refresh() +{ + int rows = numRows(); + QString value; + AbTableItem *abi; + for ( int r = 0; r < rows; ++r ) { + abi = static_cast( item(r, 0) ); + value = findContactContact( contactList[abi] ); + static_cast( item(r, 1) )->setItem( value, abi->text() ); + } + resort(); +} + +void AbTable::keyPressEvent( QKeyEvent *e ) +{ + char key = toupper( e->ascii() ); + + if ( key >= 'A' && key <= 'Z' ) + moveTo( key ); + + switch( e->key() ) { + case Qt::Key_Space: + case Qt::Key_Return: + case Qt::Key_Enter: + emit details(); + break; + default: + QTable::keyPressEvent( e ); + } +} + +void AbTable::moveTo( char c ) +{ + + int rows = numRows(); + QString value; + AbTableItem *abi; + int r; + if ( asc ) { + r = 0; + while ( r < rows-1) { + abi = static_cast( item(r, 0) ); + QChar first = abi->key()[0]; + //### is there a bug in QChar to char comparison??? + if ( first.row() || first.cell() >= c ) + break; + r++; + } + } else { + //### should probably disable reverse sorting instead + r = rows - 1; + while ( r > 0 ) { + abi = static_cast( item(r, 0) ); + QChar first = abi->key()[0]; + //### is there a bug in QChar to char comparison??? + if ( first.row() || first.cell() >= c ) + break; + r--; + } + } + setCurrentCell( r, currentColumn() ); +} + + +QString AbTable::findContactName( const Contact &entry ) +{ + // We use the fileAs, then company, defaultEmail + QString str; + str = entry.fileAs(); + if ( str.isEmpty() ) { + str = entry.company(); + if ( str.isEmpty() ) { + str = entry.defaultEmail(); + } + } + return str; +} + +QString AbTable::findContactContact( const Contact &entry ) +{ + QString value; + value = ""; + for ( QValueList::ConstIterator it = intFields->begin(); + it != intFields->end(); ++it ) { + switch ( *it ) { + default: + break; + case Qtopia::Title: + value = entry.title(); + break; + case Qtopia::Suffix: + value = entry.suffix(); + break; + case Qtopia::FileAs: + value = entry.fileAs(); + break; + case Qtopia::DefaultEmail: + value = entry.defaultEmail(); + case Qtopia::Emails: + value = entry.emails(); + break; + case Qtopia::HomeStreet: + value = entry.homeStreet(); + break; + case Qtopia::HomeCity: + value = entry.homeCity(); + break; + case Qtopia::HomeState: + value = entry.homeState(); + break; + case Qtopia::HomeZip: + value = entry.homeZip(); + break; + case Qtopia::HomeCountry: + value = entry.homeCountry(); + break; + case Qtopia::HomePhone: + value = entry.homePhone(); + break; + case Qtopia::HomeFax: + value = entry.homeFax(); + break; + case Qtopia::HomeMobile: + value = entry.homeMobile(); + break; + case Qtopia::HomeWebPage: + value = entry.homeWebpage(); + break; + case Qtopia::Company: + value = entry.company(); + break; + case Qtopia::BusinessCity: + value = entry.businessCity(); + break; + case Qtopia::BusinessStreet: + value = entry.businessStreet(); + break; + case Qtopia::BusinessZip: + value = entry.businessZip(); + break; + case Qtopia::BusinessCountry: + value = entry.businessCountry(); + break; + case Qtopia::BusinessWebPage: + value = entry.businessWebpage(); + break; + case Qtopia::JobTitle: + value = entry.jobTitle(); + break; + case Qtopia::Department: + value = entry.department(); + break; + case Qtopia::Office: + value = entry.office(); + break; + case Qtopia::BusinessPhone: + value = entry.businessPhone(); + break; + case Qtopia::BusinessFax: + value = entry.businessFax(); + break; + case Qtopia::BusinessMobile: + value = entry.businessMobile(); + break; + case Qtopia::BusinessPager: + value = entry.businessPager(); + break; + case Qtopia::Profession: + value = entry.profession(); + break; + case Qtopia::Assistant: + value = entry.assistant(); + break; + case Qtopia::Manager: + value = entry.manager(); + break; + case Qtopia::Spouse: + value = entry.spouse(); + break; + case Qtopia::Gender: + value = entry.gender(); + break; + case Qtopia::Birthday: + value = entry.birthday(); + break; + case Qtopia::Anniversary: + value = entry.anniversary(); + break; + case Qtopia::Nickname: + value = entry.nickname(); + break; + case Qtopia::Children: + value = entry.children(); + break; + case Qtopia::Notes: + value = entry.notes(); + break; + } + if ( !value.isEmpty() ) + break; + } + return value; +} + +void AbTable::addEntry( const Contact &newCnt ) +{ + int row = numRows(); + setNumRows( row + 1 ); + updateJournal( newCnt, Contact::ACTION_ADD ); + insertIntoTable( newCnt, row ); + setCurrentCell( row, 0 ); + updateVisible(); +} + +void AbTable::updateJournal( const Contact &cnt, + Contact::journal_action action, int row ) +{ + QFile f( journalFileName() ); + if ( !f.open(IO_WriteOnly|IO_Append) ) + return; + QString buf; + QCString str; + buf = "\n" + " \n" + " \n" + " \n"; + QMapIterator it; + for ( it = contactList.begin(); it != contactList.end(); ++it ) { + out += " list; + list.setAutoDelete( TRUE ); + QByteArray ba = f.readAll(); + f.close(); + char *uc = ba.data();//(QChar *)data.unicode(); + int len = ba.size();//data.length(); + bool foundAction = false; + Contact::journal_action action; + bool foundKey = false; + int journalKey = 0; + + const int JOURNALACTION = Qtopia::Notes + 1; + const int JOURNALROW = JOURNALACTION + 1; + + // ********************************** + // CHANGE THE SIZE OF THE DICT IF YOU ADD ANY MORE FIELDS!!!! + // ********************************** + QAsciiDict dict( 47 ); + dict.setAutoDelete( TRUE ); + dict.insert( "Uid", new int(Qtopia::AddressUid) ); + dict.insert( "Title", new int(Qtopia::Title) ); + dict.insert( "FirstName", new int(Qtopia::FirstName) ); + dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); + dict.insert( "LastName", new int(Qtopia::LastName) ); + dict.insert( "Suffix", new int(Qtopia::Suffix) ); + dict.insert( "FileAs", new int(Qtopia::FileAs) ); + dict.insert( "Categories", new int(Qtopia::AddressCategory) ); + dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); + dict.insert( "Emails", new int(Qtopia::Emails) ); + dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); + dict.insert( "HomeCity", new int(Qtopia::HomeCity) ); + dict.insert( "HomeState", new int(Qtopia::HomeState) ); + dict.insert( "HomeZip", new int(Qtopia::HomeZip) ); + dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) ); + dict.insert( "HomePhone", new int(Qtopia::HomePhone) ); + dict.insert( "HomeFax", new int(Qtopia::HomeFax) ); + dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) ); + dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) ); + dict.insert( "Company", new int(Qtopia::Company) ); + dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); + dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); + dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); + dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); + dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); + dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); + dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); + dict.insert( "Department", new int(Qtopia::Department) ); + dict.insert( "Office", new int(Qtopia::Office) ); + dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); + dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); + dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); + dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); + dict.insert( "Profession", new int(Qtopia::Profession) ); + dict.insert( "Assistant", new int(Qtopia::Assistant) ); + dict.insert( "Manager", new int(Qtopia::Manager) ); + dict.insert( "Spouse", new int(Qtopia::Spouse) ); + dict.insert( "Children", new int(Qtopia::Children) ); + dict.insert( "Gender", new int(Qtopia::Gender) ); + dict.insert( "Birthday", new int(Qtopia::Birthday) ); + dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); + dict.insert( "Nickname", new int(Qtopia::Nickname) ); + dict.insert( "Notes", new int(Qtopia::Notes) ); + dict.insert( "action", new int(JOURNALACTION) ); + dict.insert( "actionrow", new int(JOURNALROW) ); + + int i = 0; + int num = 0; + char *point; + while ( (point = strstr( uc+i, "= len-2 || (uc[i] == '/' && uc[i+1] == '>') ) + break; + // we have another attribute read it. + int j = i; + while ( j < len && uc[j] != '=' ) + j++; + char *attr = uc+i; + uc[j] = '\0'; + //qDebug("attr=%s", attr.latin1() ); + i = ++j; // skip = + while ( i < len && uc[i] != '"' ) + i++; + j = ++i; + bool haveEnt = FALSE; + bool haveUtf = FALSE; + while ( j < len && uc[j] != '"' ) { + if ( uc[j] == '&' ) + haveEnt = TRUE; + if ( ((unsigned char)uc[j]) > 0x7f ) + haveUtf = TRUE; + j++; + } + + if ( j == i ) { + // empty value + i = j + 1; + continue; + } + + QString value = haveUtf ? QString::fromUtf8( uc+i, j-i ) + : QString::fromLatin1( uc+i, j-i ); + if ( haveEnt ) + value = Qtopia::plainString( value ); + i = j + 1; + + int *find = dict[ attr ]; + if ( !find ) { + cnt->setCustomField(attr, value); + continue; + } +#if 1 + switch( *find ) { + case Qtopia::AddressUid: + cnt->setUid( value.toInt() ); + break; + case Qtopia::AddressCategory: + cnt->setCategories( Qtopia::Record::idsFromString( value )); + break; + case JOURNALACTION: + action = Contact::journal_action(value.toInt()); + break; + case JOURNALROW: + journalKey = value.toInt(); + break; + + default: + cnt->insert( *find, value ); + break; + } +#endif + } + + // sadly we can't delay adding of items from the journal to get + // the proper effect, but then, the journal should _never_ be + // that huge, and recovering from a crash is not necessarily + // a *fast* thing. + switch ( action ) { + case Contact::ACTION_ADD: + if ( journalFile ) { + int myrows = numRows(); + setNumRows( myrows + 1 ); + insertIntoTable( *cnt, myrows ); + delete cnt; + } + else + list.append( cnt ); + break; + case Contact::ACTION_REMOVE: + // yup, we don't use the entry to remove the object... + journalFreeRemove( journalKey ); + delete cnt; + break; + case Contact::ACTION_REPLACE: + journalFreeReplace( *cnt, journalKey ); + delete cnt; + break; + default: + break; + } + num++; + foundAction = false; + foundKey = false; +// if ( num % 100 == 0 ) { +// qDebug("loading file, num=%d, t=%d", num, t.elapsed() ); +// } + } + if ( list.count() > 0 ) { + internalAddEntries( list ); + } +// qDebug("done loading %d, t=%d", num, t.elapsed() ); + +} + +void AbTable::realignTable( int row ) +{ + QTableItem *ti1, + *ti2; + int totalRows = numRows(); + for ( int curr = row; curr < totalRows - 1; curr++ ) { + // the same info from the todo list still applies, but I + // don't think it is _too_ bad. + ti1 = item( curr + 1, 0 ); + ti2 = item( curr + 1, 1 ); + takeItem( ti1 ); + takeItem( ti2 ); + setItem( curr, 0, ti1 ); + setItem( curr, 1, ti2 ); + } + setNumRows( totalRows - 1 ); + resort(); +} + +void AbTable::insertIntoTable( const Contact &cnt, int row ) +{ + QString strName, + strContact; + + strName = findContactName( cnt ); + strContact = findContactContact( cnt ); + + AbTableItem *ati; + ati = new AbTableItem( this, QTableItem::Never, strName, strContact); + contactList.insert( ati, cnt ); + setItem( row, 0, ati ); + ati = new AbTableItem( this, QTableItem::Never, strContact, strName); + setItem( row, 1, ati ); + + //### cannot do this; table only has two columns at this point + // setItem( row, 2, new AbPickItem( this ) ); + + // resort at some point? +} + +void AbTable::internalAddEntries( QList &list ) +{ + setUpdatesEnabled( FALSE ); + setNumRows( list.count() ); + int row = 0; + Contact *it; + for ( it = list.first(); it; it = list.next() ) + insertIntoTable( *it, row++ ); + resort(); + setUpdatesEnabled( TRUE ); +} + + +void AbTable::journalFreeReplace( const Contact &cnt, int row ) +{ + QString strName, + strContact; + AbTableItem *ati; + + strName = findContactName( cnt ); + strContact = findContactContact( cnt ); + ati = static_cast(item(row, 0)); + contactList.remove( ati ); + ati->setItem( strName, strContact ); + contactList.insert( ati, cnt ); + + ati = static_cast(item(row, 1)); + ati->setItem( strContact, strName ); +} + +void AbTable::journalFreeRemove( int row ) +{ + AbTableItem *ati; + ati = static_cast(item(row, 0)); + if ( !ati ) + return; + contactList.remove( ati ); + realignTable( row ); +} + +#if QT_VERSION <= 230 +#ifndef SINGLE_APP +void QTable::paintEmptyArea( QPainter *p, int cx, int cy, int cw, int ch ) +{ + // Region of the rect we should draw + QRegion reg( QRect( cx, cy, cw, ch ) ); + // Subtract the table from it + reg = reg.subtract( QRect( QPoint( 0, 0 ), tableSize() ) ); + // And draw the rectangles (transformed as needed) + QArray r = reg.rects(); + for (unsigned int i=0; ifillRect( r[i], colorGroup().brush( QColorGroup::Base ) ); +} +#endif +#endif + + +// int AbTable::rowHeight( int ) const +// { +// return 18; +// } + +// int AbTable::rowPos( int row ) const +// { +// return 18*row; +// } + +// int AbTable::rowAt( int pos ) const +// { +// return QMIN( pos/18, numRows()-1 ); +// } + +void AbTable::slotDoFind( const QString &findString, bool caseSensitive, + bool backwards, int category ) +{ + if ( currFindRow < -1 ) + currFindRow = currentRow() - 1; + clearSelection( TRUE ); + int rows, + row; + AbTableItem *ati; + QRegExp r( findString ); + r.setCaseSensitive( caseSensitive ); + rows = numRows(); + static bool wrapAround = true; + + if ( !backwards ) { + for ( row = currFindRow + 1; row < rows; row++ ) { + ati = static_cast( item(row, 0) ); + if ( contactCompare( contactList[ati], r, category ) ) + break; + + } + } else { + for ( row = currFindRow - 1; row > -1; row-- ) { + ati = static_cast( item(row, 0) ); + if ( contactCompare( contactList[ati], r, category ) ) + break; + } + } + if ( row >= rows || row < 0 ) { + if ( row < 0 ) + currFindRow = rows; + else + currFindRow = -1; + + if ( wrapAround ) + emit signalWrapAround(); + else + emit signalNotFound(); + + wrapAround = !wrapAround; + } else { + currFindRow = row; + QTableSelection foundSelection; + foundSelection.init( currFindRow, 0 ); + foundSelection.expandTo( currFindRow, numCols() - 1 ); + addSelection( foundSelection ); + setCurrentCell( currFindRow, numCols() - 1 ); + wrapAround = true; + } +} + +static bool contactCompare( const Contact &cnt, const QRegExp &r, int category ) +{ + bool returnMe; + QArray cats; + cats = cnt.categories(); + + returnMe = false; + if ( (category == -1 && cats.count() == 0) || category == -2 ) + returnMe = cnt.match( r ); + else { + int i; + for ( i = 0; i < int(cats.count()); i++ ) { + if ( cats[i] == category ) { + returnMe = cnt.match( r ); + break; + } + } + } + return returnMe; +} + +void AbTable::fitColumns() +{ + int contentsWidth = visibleWidth(); + int n = numCols(); + int pw = n == 3 ? columnWidth(2) : 0; + setColumnWidth( 0, contentsWidth - contentsWidth / 2 ); + setColumnWidth( 1, contentsWidth / 2 - pw ); +} + +void AbTable::show() +{ + fitColumns(); + QTable::show(); +} + +void AbTable::setChoiceNames( const QStringList& list) +{ + choicenames = list; + if ( choicenames.isEmpty() ) { + // hide pick column + setNumCols( 2 ); + } else { + // show pick column + setNumCols( 3 ); + setColumnWidth( 2, fontMetrics().width(tr( "Pick" ))+8 ); + horizontalHeader()->setLabel( 2, tr( "Pick" )); + } + fitColumns(); +} + +void AbTable::itemClicked(int,int col) +{ + if ( col == 2 ) { + return; + } else { + emit details(); + } +} + +QStringList AbTable::choiceNames() const +{ + return choicenames; +} + +void AbTable::setChoiceSelection(int /*index*/, const QStringList& /*list*/) +{ + /* ###### + + QString selname = choicenames.at(index); + for (each row) { + Contact *c = contactForRow(row); + if ( list.contains(c->email) ) { + list.remove(c->email); + setText(row, 2, selname); + } + } + for (remaining list items) { + Contact *c = new contact(item); + setText(newrow, 2, selname); + } + + */ +} + +QStringList AbTable::choiceSelection(int /*index*/) const +{ + QStringList r; + /* ###### + + QString selname = choicenames.at(index); + for (each row) { + Contact *c = contactForRow(row); + if ( text(row,2) == selname ) { + r.append(c->email); + } + } + + */ + return r; +} + +void AbTable::setShowCategory( const QString &c ) +{ + showCat = c; + updateVisible(); +} + +QString AbTable::showCategory() const +{ + return showCat; +} + + +QStringList AbTable::categories() +{ + mCat.load( categoryFileName() ); + QStringList categoryList = mCat.labels( "Contacts" ); + return categoryList; +} + +void AbTable::updateVisible() +{ + int visible, + totalRows, + id, + totalCats, + it, + row; + bool hide; + AbTableItem *ati; + Contact *cnt; + visible = 0; + + setPaintingEnabled( FALSE ); + + totalRows = numRows(); + id = mCat.id( "Contacts", showCat ); + QArray cats; + for ( row = 0; row < totalRows; row++ ) { + ati = static_cast( item(row, 0) ); + cnt = &contactList[ati]; + cats = cnt->categories(); + hide = false; + if ( !showCat.isEmpty() ) { + if ( showCat == tr( "Unfiled" ) ) { + if ( cats.count() > 0 ) + hide = true; + } else { + // do some comparing + if ( !hide ) { + hide = true; + totalCats = int(cats.count()); + for ( it = 0; it < totalCats; it++ ) { + if ( cats[it] == id ) { + hide = false; + break; + } + } + } + } + } + if ( hide ) { + if ( currentRow() == row ) + setCurrentCell( -1, 0 ); + if ( rowHeight(row) > 0 ) + hideRow( row ); + } else { + if ( rowHeight(row) == 0 ) { + showRow( row ); + adjustRow( row ); + } + visible++; + } + } + if ( !visible ) + setCurrentCell( -1, 0 ); + + setPaintingEnabled( TRUE ); +} + + +void AbTable::setPaintingEnabled( bool e ) +{ + if ( e != enablePainting ) { + if ( !enablePainting ) { + enablePainting = true; + rowHeightChanged( 0 ); + viewport()->update(); + } else { + enablePainting = false; + } + } +} + +void AbTable::rowHeightChanged( int row ) +{ + if ( enablePainting ) + QTable::rowHeightChanged( row ); +} diff --git a/core/pim/addressbook/abtable.h b/core/pim/addressbook/abtable.h new file mode 100644 index 0000000..9b96997 --- a/dev/null +++ b/core/pim/addressbook/abtable.h @@ -0,0 +1,140 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef ABTABLE_H +#define ABTABLE_H + +#include +#include + +#include +#include +#include +#include + +class AbTableItem : public QTableItem +{ +public: + AbTableItem( QTable *t, EditType et, const QString &s, + const QString &secondSortKey); + QString entryKey() const; + void setEntryKey( const QString & k ); + virtual int alignment() const; + virtual QString key() const; + void setItem( const QString &txt, const QString &secondKey ); + +private: + QString sortKey; +}; + +class AbPickItem : public QTableItem +{ +public: + AbPickItem( QTable *t ); + + QWidget *createEditor() const; + void setContentFromEditor( QWidget *w ); + +private: + QGuardedPtr cb; +}; + +class AbTable : public QTable +{ + Q_OBJECT + +public: + AbTable( const QValueList *ordered, QWidget *parent, const char *name=0 ); + ~AbTable(); + // NEW + void addEntry( const Contact &newContact ); + Contact currentEntry(); + void replaceCurrentEntry( const Contact &newContact ); + + void init(); + + void deleteCurrentEntry(); + void clear(); + void clearFindRow() { currFindRow = -2; } + void loadFields(); + void refresh(); + bool save( const QString &fn ); + void load( const QString &fn ); + + // addresspicker mode + void setChoiceNames( const QStringList& list); + QStringList choiceNames() const; + void setChoiceSelection(int index, const QStringList& list); + QStringList choiceSelection(int index) const; + void setShowCategory( const QString &c ); + QString showCategory() const; + QStringList categories(); + + void show(); + void setPaintingEnabled( bool e ); + +public slots: + void slotDoFind( const QString &str, bool caseSensitive, bool backwards, + int category ); +signals: + void empty( bool ); + void details(); + void signalNotFound(); + void signalWrapAround(); + +protected: + virtual void keyPressEvent( QKeyEvent *e ); + +// int rowHeight( int ) const; +// int rowPos( int row ) const; +// virtual int rowAt( int pos ) const; + + +protected slots: + void moveTo( char ); + virtual void columnClicked( int col ); + void itemClicked(int,int col); + void rowHeightChanged( int row ); + +private: + void loadFile( const QString &strFile, bool journalFile ); + void fitColumns(); + void resort(); + void updateJournal( const Contact &contact, Contact::journal_action action, + int row = -1 ); + void insertIntoTable( const Contact &contact, int row ); + void internalAddEntries( QList &list ); + QString findContactName( const Contact &entry ); + QString findContactContact( const Contact &entry ); + void journalFreeReplace( const Contact &cnt, int row ); + void journalFreeRemove( int row ); + void realignTable( int ); + void updateVisible(); + int lastSortCol; + bool asc; + QMap contactList; + const QValueList *intFields; + int currFindRow; + QString showCat; + QStringList choicenames; + bool enablePainting; + Categories mCat; +}; +#endif // ABTABLE_H diff --git a/core/pim/addressbook/addressbook.cpp b/core/pim/addressbook/addressbook.cpp new file mode 100644 index 0000000..b694e4f --- a/dev/null +++ b/core/pim/addressbook/addressbook.cpp @@ -0,0 +1,829 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "abeditor.h" +#include "ablabel.h" +#include "abtable.h" +#include "addresssettings.h" +#include "addressbook.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +static QString addressbookOldXMLFilename() +{ + QString filename = QPEApplication::documentDir() + "addressbook.xml"; + return filename; +} + +static QString addressbookXMLFilename() +{ + QString filename = Global::applicationFileName("addressbook", + "addressbook.xml"); + return filename; +} + +static QString addressbookPersonalVCardName() +{ + QString filename = Global::applicationFileName("addressbook", + "businesscard.vcf"); + return filename; +} + + +AddressbookWindow::AddressbookWindow( QWidget *parent, const char *name, + WFlags f ) + : QMainWindow( parent, name, f ), + abEditor(0), + bAbEditFirstTime(TRUE), + syncing(FALSE) +{ + initFields(); + + setCaption( tr("Contacts") ); + setIcon( Resource::loadPixmap( "AddressBook" ) ); + + setToolBarsMovable( FALSE ); + + // Create Toolbars + + QPEToolBar *bar = new QPEToolBar( this ); + bar->setHorizontalStretchable( TRUE ); + + QPEMenuBar *mbList = new QPEMenuBar( bar ); + mbList->setMargin( 0 ); + + QPopupMenu *edit = new QPopupMenu( this ); + mbList->insertItem( tr( "Contact" ), edit ); + + listTools = new QPEToolBar( this, "list operations" ); + + + QAction *a = new QAction( tr( "New" ), Resource::loadPixmap( "new" ), QString::null, + 0, this, 0 ); + actionNew = a; + connect( a, SIGNAL( activated() ), this, SLOT( slotListNew() ) ); + a->addTo( edit ); + a->addTo( listTools ); + + a = new QAction( tr( "Edit" ), Resource::loadPixmap( "edit" ), QString::null, + 0, this, 0 ); + actionEdit = a; + connect( a, SIGNAL( activated() ), this, SLOT( slotViewEdit() ) ); + a->addTo( edit ); + a->addTo( listTools ); + + a = new QAction( tr( "Delete" ), Resource::loadPixmap( "trash" ), QString::null, + 0, this, 0 ); + actionTrash = a; + connect( a, SIGNAL( activated() ), this, SLOT( slotListDelete() ) ); + a->addTo( edit ); + a->addTo( listTools ); + + a = new QAction( tr( "Find" ), Resource::loadPixmap( "mag" ), + QString::null, 0, this, 0 ); + actionFind = a; + connect( a, SIGNAL(activated()), this, SLOT(slotFind()) ); + a->addTo( edit ); + a->addTo( listTools ); + + + a = new QAction( tr( "Write Mail To" ), Resource::loadPixmap( "qtmail/reply" ), + QString::null, 0, this, 0 ); + a->setEnabled( FALSE ); + actionMail = a; + connect( a, SIGNAL( activated() ), this, SLOT( writeMail() ) ); + a->addTo( edit ); + a->addTo( listTools ); + + + + if ( Ir::supported() ) { + a = new QAction( tr ("Beam Entry" ), Resource::loadPixmap( "beam" ), QString::null, + 0, this, 0 ); + actionBeam = a; + connect( a, SIGNAL( activated() ), this, SLOT( slotBeam() ) ); + a->addTo( edit ); + a->addTo( listTools ); + } + + edit->insertSeparator(); + + a = new QAction( tr("My Personal Details"), QString::null, 0, 0, 0, TRUE ); + actionPersonal = a; + connect( a, SIGNAL( activated() ), this, SLOT( slotPersonalView() ) ); + a->addTo( edit ); + + + a = new QAction( tr( "Arrange Edit Fields"), QString::null, 0, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( slotSettings() ) ); + a->addTo( edit ); + + // Create Views + + // This is safe to call without checking to see if it exists... + // not to mention it also does the necessary stuff for the + // journaling... + QString str = addressbookXMLFilename(); + if ( str.isNull() ) { + QMessageBox::warning( this, tr("Out of Space"), + tr("There is not enough space to create\n" + "neccessary startup files.\n" + "\nFree up some space before\nentering data!") + ); + } + + abList = new AbTable( &orderedFields, this, "table" ); + abList->setHScrollBarMode( QScrollView::AlwaysOff ); + connect( abList, SIGNAL( empty( bool ) ), + this, SLOT( listIsEmpty( bool ) ) ); + connect( abList, SIGNAL( details() ), + this, SLOT( slotListView() ) ); + connect( abList, SIGNAL(currentChanged(int,int)), + this, SLOT(slotUpdateToolbar()) ); + + mView = 0; + + abList->load( addressbookXMLFilename() ); + if ( QFile::exists(addressbookOldXMLFilename()) ) { + abList->load( addressbookOldXMLFilename() ); + QFile::remove(addressbookOldXMLFilename()); + } + + catMenu = new QPopupMenu( this ); + catMenu->setCheckable( TRUE ); + connect( catMenu, SIGNAL(activated(int)), this, SLOT(slotSetCategory(int)) ); + populateCategories(); + + mbList->insertItem( tr("View"), catMenu ); + setCentralWidget( abList ); + + // qDebug("adressbook contrsuction: t=%d", t.elapsed() ); +} + +void AddressbookWindow::setDocument( const QString &filename ) +{ + if ( filename.find(".vcf") != int(filename.length()) - 4 ) return; + + QValueList cl = Contact::readVCard( filename ); + for( QValueList::Iterator it = cl.begin(); it != cl.end(); ++it ) { +// QString msg = tr("You received a vCard for\n%1.\nDo You want to add it to your\naddressbook?") +// .arg( (*it).fullName() ); +// if ( QMessageBox::information( this, tr("received contact"), msg, QMessageBox::Ok, QMessageBox::Cancel ) == +// QMessageBox::Ok ) { + abList->addEntry( *it ); +// } + } + +} + +void AddressbookWindow::resizeEvent( QResizeEvent *e ) +{ + QMainWindow::resizeEvent( e ); + + if ( centralWidget() == abList ) + showList(); + else if ( centralWidget() == mView ) + showView(); +} + +AddressbookWindow::~AddressbookWindow() +{ +} + +void AddressbookWindow::slotUpdateToolbar() +{ + Contact ce = abList->currentEntry(); + actionMail->setEnabled( !ce.defaultEmail().isEmpty() ); +} + +void AddressbookWindow::showList() +{ + if ( mView ) mView->hide(); + setCentralWidget( abList ); + abList->show(); + // update our focues... (or use a stack widget!); + abList->setFocus(); +} + +void AddressbookWindow::showView() +{ + if ( abList->numRows() > 0 ) { + abList->hide(); + setCentralWidget( abView() ); + mView->show(); + mView->setFocus(); + } +} + +void AddressbookWindow::slotListNew() +{ + Contact cnt; + if( !syncing ) { + if ( abEditor ) + abEditor->setEntry( cnt ); + abView()->init( cnt ); + editEntry( NewEntry ); + } else { + QMessageBox::warning(this, tr("Contacts"), + tr("Can not edit data, currently syncing")); + } +} + +void AddressbookWindow::slotListView() +{ + abView()->init( abList->currentEntry() ); + mView->sync(); + showView(); +} + +void AddressbookWindow::slotListDelete() +{ + if(!syncing) { + Contact tmpEntry = abList->currentEntry(); + + // get a name, do the best we can... + QString strName = tmpEntry.fullName(); + if ( strName.isEmpty() ) { + strName = tmpEntry.company(); + if ( strName.isEmpty() ) + strName = "No Name"; + } + + + if ( QPEMessageBox::confirmDelete( this, tr( "Contacts" ), + strName ) ) { + abList->deleteCurrentEntry(); + showList(); + } + } else { + QMessageBox::warning( this, tr("Contacts"), + tr("Can not edit data, currently syncing") ); + } +} + +void AddressbookWindow::slotViewBack() +{ + showList(); +} + +void AddressbookWindow::slotViewEdit() +{ + if(!syncing) { + if (actionPersonal->isOn()) { + editPersonal(); + } else { + if ( !bAbEditFirstTime ) + abEditor->setEntry( abList->currentEntry() ); + editEntry( EditEntry ); + } + } else { + QMessageBox::warning( this, tr("Contacts"), + tr("Can not edit data, currently syncing") ); + } +} + + + +void AddressbookWindow::writeMail() +{ + Contact c = abList->currentEntry(); + QString name = c.fileAs(); + QString email = c.defaultEmail(); + QCopEnvelope e("QPE/Application/qtmail", "writeMail(QString,QString)"); + e << name << email; +} + + + + +static const char * beamfile = "/tmp/obex/contact.vcf"; + +void AddressbookWindow::slotBeam() +{ + QString filename; + Contact c; + if ( actionPersonal->isOn() ) { + filename = addressbookPersonalVCardName(); + if (!QFile::exists(filename)) + return; // can't beam a non-existent file + c = Contact::readVCard( filename )[0]; + } else { + unlink( beamfile ); // delete if exists + c = abList->currentEntry(); + mkdir("/tmp/obex/", 0755); + Contact::writeVCard( beamfile, c ); + filename = beamfile; + } + Ir *ir = new Ir( this ); + connect( ir, SIGNAL( done( Ir * ) ), this, SLOT( beamDone( Ir * ) ) ); + QString description = c.fullName(); + ir->send( filename, description, "text/x-vCard" ); +} + +void AddressbookWindow::beamDone( Ir *ir ) +{ + delete ir; + unlink( beamfile ); +} + + +static void parseName( const QString& name, QString *first, QString *middle, + QString * last ) +{ + + int comma = name.find ( "," ); + QString rest; + if ( comma > 0 ) { + *last = name.left( comma ); + comma++; + while ( comma < int(name.length()) && name[comma] == ' ' ) + comma++; + rest = name.mid( comma ); + } else { + int space = name.findRev( ' ' ); + *last = name.mid( space+1 ); + rest = name.left( space ); + } + int space = rest.find( ' ' ); + if ( space <= 0 ) { + *first = rest; + } else { + *first = rest.left( space ); + *middle = rest.mid( space+1 ); + } + +} + + +void AddressbookWindow::appMessage(const QCString &msg, const QByteArray &data) +{ + if (msg == "editPersonal()") { + editPersonal(); + } else if (msg == "editPersonalAndClose()") { + editPersonal(); + close(); + } else if ( msg == "addContact(QString,QString)" ) { + QDataStream stream(data,IO_ReadOnly); + QString name, email; + stream >> name >> email; + + Contact cnt; + QString fn, mn, ln; + parseName( name, &fn, &mn, &ln ); + // qDebug( " %s - %s - %s", fn.latin1(), mn.latin1(), ln.latin1() ); + cnt.setFirstName( fn ); + cnt.setMiddleName( mn ); + cnt.setLastName( ln ); + cnt.setEmails( email ); + cnt.setDefaultEmail( email ); + cnt.setFileAs(); + + if ( bAbEditFirstTime ) { + abEditor = new AbEditor( cnt, &orderedFields, &slOrderedFields, + this, "editor" ); + bAbEditFirstTime = FALSE; + } else { + abEditor->setEntry( cnt ); + } + abView()->init( cnt ); + editEntry( NewEntry ); + + + + } +#if 0 + else if (msg == "pickAddresses(QCString,QCString,QStringList,...)" ) { + QDataStream stream(data,IO_ReadOnly); + QCString ch,m; + QStringList types; + stream >> ch >> m >> types; + AddressPicker picker(abList,this,0,TRUE); + picker.showMaximized(); + picker.setChoiceNames(types); + int i=0; + for (QStringList::ConstIterator it = types.begin(); it!=types.end(); ++it) { + QStringList sel; + stream >> sel; + picker.setSelection(i++,sel); + } + picker.showMaximized(); + picker.exec(); + + // ###### note: contacts may have been added - save here! + + setCentralWidget(abList); + QCopEnvelope e(ch,m); + i=0; + for (QStringList::ConstIterator it = types.begin(); it!=types.end(); ++it) { + QStringList sel = picker.selection(i++); + e << sel; + } + } +#endif + +} + +void AddressbookWindow::editPersonal() +{ + QString filename = addressbookPersonalVCardName(); + Contact me; + if (QFile::exists(filename)) + me = Contact::readVCard( filename )[0]; + if (bAbEditFirstTime) { + abEditor = new AbEditor( me, &orderedFields, &slOrderedFields, + this, "editor" ); + // don't create a new editor every time + bAbEditFirstTime = FALSE; + } else + abEditor->setEntry( me ); + + abEditor->setCaption(tr("Edit My Personal Details")); + abEditor->showMaximized(); + + // fix the foxus... + abEditor->setNameFocus(); + if ( abEditor->exec() ) { + setFocus(); + Contact new_personal = abEditor->entry(); + QString fname = addressbookPersonalVCardName(); + Contact::writeVCard( fname, new_personal ); + abView()->init(new_personal); + abView()->sync(); + } + abEditor->setCaption( tr("Edit Address") ); +} + +void AddressbookWindow::slotPersonalView() +{ + if (!actionPersonal->isOn()) { + // we just turned it off + setCaption( tr("Contacts") ); + actionNew->setEnabled(TRUE); + actionTrash->setEnabled(TRUE); + actionFind->setEnabled(TRUE); + slotUpdateToolbar(); // maybe some of the above could be moved there + showList(); + return; + } + + // XXX need to disable some QActions. + actionNew->setEnabled(FALSE); + actionTrash->setEnabled(FALSE); + actionFind->setEnabled(FALSE); + actionMail->setEnabled(FALSE); + + setCaption( tr("Contacts - My Personal Details") ); + QString filename = addressbookPersonalVCardName(); + Contact me; + if (QFile::exists(filename)) + me = Contact::readVCard( filename )[0]; + + abView()->init( me ); + abView()->sync(); + abList->hide(); + setCentralWidget( abView() ); + mView->show(); + mView->setFocus(); +} + +void AddressbookWindow::editEntry( EntryMode entryMode ) +{ + Contact entry; + if ( bAbEditFirstTime ) { + abEditor = new AbEditor( entry, &orderedFields, &slOrderedFields, + this, "editor" ); + bAbEditFirstTime = FALSE; + if ( entryMode == EditEntry ) + abEditor->setEntry( abList->currentEntry() ); + } + // other things may chane the caption. + abEditor->setCaption( tr("Edit Address") ); + +#if defined(Q_WS_QWS) || defined(_WS_QWS_) + abEditor->showMaximized(); +#endif + // fix the foxus... + abEditor->setNameFocus(); + if ( abEditor->exec() ) { + setFocus(); + if ( entryMode == NewEntry ) { + Contact insertEntry = abEditor->entry(); + insertEntry.assignUid(); + abList->addEntry( insertEntry ); + } else { + Contact replaceEntry = abEditor->entry(); + if ( !replaceEntry.isValidUid() ) + replaceEntry.assignUid(); + abList->replaceCurrentEntry( replaceEntry ); + } + } + populateCategories(); + showList(); +} + +void AddressbookWindow::listIsEmpty( bool empty ) +{ + if ( !empty ) { + deleteButton->setEnabled( TRUE ); + } +} + +void AddressbookWindow::reload() +{ + syncing = FALSE; + abList->clear(); + abList->load( addressbookXMLFilename() ); +} + +void AddressbookWindow::flush() +{ + syncing = TRUE; + abList->save( addressbookXMLFilename() ); +} + + +void AddressbookWindow::closeEvent( QCloseEvent *e ) +{ + if ( centralWidget() == mView ) { + if (actionPersonal->isOn()) { + // pretend we clicked it off + actionPersonal->setOn(FALSE); + slotPersonalView(); + } else { + showList(); + } + e->ignore(); + return; + } + + if(syncing) { + /* shouldn't we save, I hear you say? well its already been set + so that an edit can not occur during a sync, and we flushed + at the start of the sync, so there is no need to save + Saving however itself would cause problems. */ + e->accept(); + return; + } +//################## shouldn't always save + if ( save() ) + e->accept(); + else + e->ignore(); +} + +/* + Returns TRUE if it is OK to exit + */ + +bool AddressbookWindow::save() +{ + QString str = addressbookXMLFilename(); + if ( str.isNull() ) { + if ( QMessageBox::critical( 0, tr("Out of space"), + tr("Unable to save information.\n" + "Free up some space\n" + "and try again.\n" + "\nQuit anyway?"), + QMessageBox::Yes|QMessageBox::Escape, + QMessageBox::No|QMessageBox::Default ) + != QMessageBox::No ) + return TRUE; + else + return FALSE; + } else { + if ( !abList->save( str ) ) { + if ( QMessageBox::critical( 0, tr( "Out of space" ), + tr("Unable to save information.\n" + "Free up some space\n" + "and try again.\n" + "\nQuit anyway?"), + QMessageBox::Yes|QMessageBox::Escape, + QMessageBox::No|QMessageBox::Default ) + != QMessageBox::No ) + return TRUE; + else + return FALSE; + } + } + return TRUE; +} + +void AddressbookWindow::slotSettings() +{ + AddressSettings frmSettings( this ); +#if defined(Q_WS_QWS) || defined(_WS_QWS_) + frmSettings.showMaximized(); +#endif + + if ( frmSettings.exec() ) { + allFields.clear(); + orderedFields.clear(); + slOrderedFields.clear(); + initFields(); + if ( abEditor ) + abEditor->loadFields(); + abList->refresh(); + } +} + + +void AddressbookWindow::initFields() +{ + // we really don't need the things from the configuration, anymore + // only thing that is important are the important categories. So, + // Call the contact functions that correspond to these old functions... + + QStringList xmlFields = Contact::fields(); + QStringList visibleFields = Contact::trfields(); + xmlFields.remove( "Title" ); + visibleFields.remove( tr("Name Title") ); + visibleFields.remove( tr("Notes") ); + + int i, + version; + Config cfg( "AddressBook" ); + QString zn; + + // ### Write a function to keep this from happening again... + QStringList::ConstIterator it; + for ( i = 0, it = xmlFields.begin(); it != xmlFields.end(); ++it, i++ ) { + allFields.append( i + 3 ); + } + + cfg.setGroup( "Version" ); + version = cfg.readNumEntry( "version" ); + i = 0; + if ( version >= ADDRESSVERSION ) { + + cfg.setGroup( "ImportantCategory" ); + + zn = cfg.readEntry( "Category" + QString::number(i), QString::null ); + while ( !zn.isNull() ) { + if ( zn.contains( tr("Work") ) || zn.contains( tr("Mb") ) ) { + slOrderedFields.clear(); + break; + } + slOrderedFields.append( zn ); + zn = cfg.readEntry( "Category" + QString::number(++i), QString::null ); + } + } else { + QString str; + str = getenv("HOME"); + str += "/Settings/AddressBook.conf"; + QFile::remove( str ); + } + if ( slOrderedFields.count() > 0 ) { + for( QStringList::ConstIterator it = slOrderedFields.begin(); + it != slOrderedFields.end(); ++it ) { + QValueList::ConstIterator itVl; + QStringList::ConstIterator itVis; + itVl = allFields.begin(); + for ( itVis = visibleFields.begin(); + itVis != visibleFields.end() && itVl != allFields.end(); + ++itVis, ++itVl ) { + if ( *it == *itVis && itVl != allFields.end() ) { + orderedFields.append( *itVl ); + } + } + } + } else { + QValueList::ConstIterator it; + for ( it = allFields.begin(); it != allFields.end(); ++it ) + orderedFields.append( *it ); + + slOrderedFields = visibleFields; + orderedFields.remove( Qtopia::AddressUid ); + orderedFields.remove( Qtopia::Title ); + orderedFields.remove( Qtopia::Groups ); + orderedFields.remove( Qtopia::AddressCategory ); + orderedFields.remove( Qtopia::FirstName ); + orderedFields.remove( Qtopia::LastName ); + orderedFields.remove( Qtopia::DefaultEmail ); + orderedFields.remove( Qtopia::FileAs ); + orderedFields.remove( Qtopia::Notes ); + orderedFields.remove( Qtopia::Gender ); + slOrderedFields.remove( tr("Name Title") ); + slOrderedFields.remove( tr("First Name") ); + slOrderedFields.remove( tr("Last Name") ); + slOrderedFields.remove( tr("File As") ); + slOrderedFields.remove( tr("Default Email") ); + slOrderedFields.remove( tr("Notes") ); + slOrderedFields.remove( tr("Gender") ); + + } +} + + +AbLabel *AddressbookWindow::abView() +{ + if ( !mView ) { + mView = new AbLabel( this, "viewer" ); + mView->init( Contact() ); + connect( mView, SIGNAL( okPressed() ), this, SLOT( slotListView() ) ); + } + return mView; +} + +void AddressbookWindow::slotFind() +{ + if ( centralWidget() == abView() ) + showList(); + FindDialog frmFind( "Contacts", this ); + QObject::connect( &frmFind, SIGNAL(signalFindClicked(const QString &, bool, bool, int)), abList, SLOT(slotDoFind( const QString&,bool,bool,int))); + QObject::connect( abList, SIGNAL(signalNotFound()), &frmFind, SLOT(slotNotFound()) ); + QObject::connect( abList, SIGNAL(signalWrapAround()), &frmFind, SLOT(slotWrapAround()) ); + frmFind.exec(); + if ( abList->numSelections() ) + abList->clearSelection(); + abList->clearFindRow(); +} + +void AddressbookWindow::slotSetCategory( int c ) +{ + if ( c <= 0 ) + return; + for ( unsigned int i = 1; i < catMenu->count(); i++ ) + catMenu->setItemChecked( i, c == (int)i ); + if ( c == 1 ) { + abList->setShowCategory( QString::null ); + setCaption( tr("Contacts") + " - " + tr ( "All" ) ); + } else if ( c == (int)catMenu->count() ) { + abList->setShowCategory( tr( "Unfiled" ) ); + setCaption( tr("Contacts") + " - " + tr( "Unfiled" ) ); + } else { + QString cat = abList->categories()[c - 2]; + abList->setShowCategory( cat ); + setCaption( tr("Contacts") + " - " + cat ); + } +} + +void AddressbookWindow::populateCategories() +{ + catMenu->clear(); + + int id, + rememberId; + id = 1; + catMenu->insertItem( tr( "All" ), id++ ); + QStringList categories = abList->categories(); + categories.append( tr( "Unfiled" ) ); + for ( QStringList::Iterator it = categories.begin(); + it != categories.end(); ++it ) { + catMenu->insertItem( *it, id ); + if ( *it == abList->showCategory() ) + rememberId = id; + ++id; + } + if ( abList->showCategory().isEmpty() ) + slotSetCategory( 1 ); + else + slotSetCategory( rememberId ); +} diff --git a/core/pim/addressbook/addressbook.cw b/core/pim/addressbook/addressbook.cw new file mode 100644 index 0000000..452df36 --- a/dev/null +++ b/core/pim/addressbook/addressbook.cw @@ -0,0 +1,26 @@ + + + + AbLineEdit +

ablineedit.h
+ + -1 + -1 + + + 789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758 + + + + AbMultiLineEdit +
abmultilineedit.h
+ + -1 + -1 + + + 789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758 + +
+ + diff --git a/core/pim/addressbook/addressbook.h b/core/pim/addressbook/addressbook.h new file mode 100644 index 0000000..9694465 --- a/dev/null +++ b/core/pim/addressbook/addressbook.h @@ -0,0 +1,99 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef Addressbook_H +#define Addressbook_H + +#include + +class AbEditor; +class AbLabel; +class AbTable; +class QPEToolBar; +class QPopupMenu; +class QToolButton; +class QDialog; +class Ir; +class QAction; + +class AddressbookWindow: public QMainWindow +{ + Q_OBJECT +public: + AddressbookWindow( QWidget *parent = 0, const char *name = 0, WFlags f = 0 ); + ~AddressbookWindow(); + +protected: + void resizeEvent( QResizeEvent * e ); + void showList(); + void showView(); + enum EntryMode { NewEntry=0, EditEntry }; + void editPersonal(); + void editEntry( EntryMode ); + void closeEvent( QCloseEvent *e ); + bool save(); + +public slots: + void flush(); + void reload(); + void appMessage(const QCString &, const QByteArray &); + void setDocument( const QString & ); + +private slots: + void slotListNew(); + void slotListView(); + void slotListDelete(); + void slotViewBack(); + void slotViewEdit(); + void slotPersonalView(); + void listIsEmpty( bool ); + void slotSettings(); + void writeMail(); + void slotBeam(); + void beamDone( Ir * ); + void slotFind(); + void slotSetCategory( int ); + void slotUpdateToolbar(); + +private: + void initFields(); // inititialize our fields... + AbLabel *abView(); + void populateCategories(); + + QPopupMenu *catMenu; + QPEToolBar *listTools; + QToolButton *deleteButton; + QValueList allFields, + orderedFields; + QStringList slOrderedFields; + enum Panes { paneList=0, paneView, paneEdit }; + AbEditor *abEditor; + AbLabel *mView; + AbTable *abList; + + QAction *actionNew, *actionEdit, *actionTrash, *actionFind, *actionBeam, + *actionPersonal, *actionMail; + + bool bAbEditFirstTime; + int viewMargin; + + bool syncing; +}; + +#endif diff --git a/core/pim/addressbook/addressbook.pro b/core/pim/addressbook/addressbook.pro new file mode 100644 index 0000000..8d3401d --- a/dev/null +++ b/core/pim/addressbook/addressbook.pro @@ -0,0 +1,22 @@ +TEMPLATE = app +CONFIG = qt warn_on release +DESTDIR = $(QPEDIR)/bin +HEADERS = addressbook.h \ + abeditor.h \ + ablabel.h \ + abtable.h \ + addresssettings.h +SOURCES = main.cpp \ + addressbook.cpp \ + abeditor.cpp \ + ablabel.cpp \ + abtable.cpp \ + addresssettings.cpp +INTERFACES = addresssettingsbase.ui + +TARGET = addressbook +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe + +TRANSLATIONS = ../i18n/de/addressbook.ts diff --git a/core/pim/addressbook/addresspicker.cpp b/core/pim/addressbook/addresspicker.cpp new file mode 100644 index 0000000..79c4d43 --- a/dev/null +++ b/core/pim/addressbook/addresspicker.cpp @@ -0,0 +1,52 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "addresspicker.h" +#include "abtable.h" + +#include + +/*! + \a tab is reparented for use in the picker. Take it back out if you want + to regain ownership. +*/ +AddressPicker::AddressPicker(AbTable* tab, QWidget* parent, const char* name, bool modal) : + QDialog(parent,name,modal) +{ + QVBoxLayout* vb = new QVBoxLayout(this); + tab->reparent(this,QPoint(0,0)); + table = tab; + vb->addWidget(table); +} + +void AddressPicker::setChoiceNames(const QStringList& list) +{ + table->setChoiceNames(list); +} + +void AddressPicker::setSelection(int index, const QStringList& list) +{ + table->setChoiceSelection(index,list); +} + +QStringList AddressPicker::selection(int index) const +{ + return table->choiceSelection(index); +} diff --git a/core/pim/addressbook/addresspicker.h b/core/pim/addressbook/addresspicker.h new file mode 100644 index 0000000..8a57479 --- a/dev/null +++ b/core/pim/addressbook/addresspicker.h @@ -0,0 +1,39 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef AddressPicker_H +#define AddressPicker_H + +#include + +class AbTable; + +class AddressPicker : public QDialog { +public: + AddressPicker(AbTable* table, QWidget* parent, const char* name=0, bool modal=FALSE); + + void setChoiceNames(const QStringList&); + void setSelection(int index, const QStringList&); + QStringList selection(int index) const; + +private: + AbTable* table; +}; + +#endif diff --git a/core/pim/addressbook/addresssettings.cpp b/core/pim/addressbook/addresssettings.cpp new file mode 100644 index 0000000..e7c2210 --- a/dev/null +++ b/core/pim/addressbook/addresssettings.cpp @@ -0,0 +1,136 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + + +#include "addresssettings.h" + +#include +#include + +#include +#include + +#include + +AddressSettings::AddressSettings( QWidget *parent, const char *name ) + : AddressSettingsBase( parent, name, TRUE ) +{ + init(); +} + +AddressSettings::~AddressSettings() +{ +} + +void AddressSettings::init() +{ + QStringList slFields = Contact::trfields(); + // Make this match what is in initFields + slFields.remove( tr("Name Title") ); + slFields.remove( tr("First Name") ); + slFields.remove( tr("Last Name") ); + slFields.remove( tr("File As") ); + slFields.remove( tr("Default Email") ); + slFields.remove( tr("Notes") ); + slFields.remove( tr("Gender") ); + + + for( QStringList::Iterator it = slFields.begin(); + it != slFields.end(); ++it ) { + fieldListBox->insertItem( *it ); + } + + Config cfg( "AddressBook" ); + + cfg.setGroup( "Version" ); + int version; + version = cfg.readNumEntry( "version" ); + if ( version >= ADDRESSVERSION ) { + int i = 0; + int p = 0; + cfg.setGroup( "ImportantCategory" ); + QString zn = cfg.readEntry( "Category" + QString::number(i), + QString::null ); + while ( !zn.isNull() ) { + for ( int m = i; m < (int)fieldListBox->count(); m++ ) { + if ( fieldListBox->text( m ) == zn ) { + if ( m != p ) { + fieldListBox->removeItem( m ); + fieldListBox->insertItem( zn, p ); + } + p++; + break; + } + } + zn = cfg.readEntry( "Category" + QString::number(++i), + QString::null ); + } + + fieldListBox->setCurrentItem( 0 ); + } else { + QString str; + str = getenv("HOME"); + + str += "/Settings/AddressBook.conf"; + QFile::remove( str ); + } +} + +void AddressSettings::itemUp() +{ + int i = fieldListBox->currentItem(); + if ( i > 0 ) { + QString item = fieldListBox->currentText(); + fieldListBox->removeItem( i ); + fieldListBox->insertItem( item, i-1 ); + fieldListBox->setCurrentItem( i-1 ); + } +} + +void AddressSettings::itemDown() +{ + int i = fieldListBox->currentItem(); + if ( i < (int)fieldListBox->count() - 1 ) { + QString item = fieldListBox->currentText(); + fieldListBox->removeItem( i ); + fieldListBox->insertItem( item, i+1 ); + fieldListBox->setCurrentItem( i+1 ); + } +} + +void AddressSettings::accept() +{ + save(); + QDialog::accept(); +} + + +void AddressSettings::save() +{ + Config cfg( "AddressBook" ); + cfg.setGroup( "Version" ); + // *** To change the version change it here... + cfg.writeEntry( "version", QString::number(ADDRESSVERSION) ); + cfg.setGroup( "ImportantCategory" ); + + for ( int i = 0; i < (int)fieldListBox->count(); i++ ) { + cfg.writeEntry( "Category"+QString::number(i), fieldListBox->text(i) ); + } +} diff --git a/core/pim/addressbook/addresssettings.h b/core/pim/addressbook/addresssettings.h new file mode 100644 index 0000000..0fdfa77 --- a/dev/null +++ b/core/pim/addressbook/addresssettings.h @@ -0,0 +1,47 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef _ADDRESSSETTINGS_H_ +#define _ADDRESSSETTINGS_H_ + +#include +#include +#include "addresssettingsbase.h" + +const int ADDRESSVERSION = 3; + +class AddressSettings : public AddressSettingsBase +{ + Q_OBJECT +public: + AddressSettings( QWidget *parent = 0, const char *name = 0 ); + ~AddressSettings(); + +protected: + void accept(); + virtual void itemUp(); + virtual void itemDown(); + +private: + void init(); + void save(); +}; + +#endif // _ADDRESSSETTINGS_H_ diff --git a/core/pim/addressbook/addresssettingsbase.ui b/core/pim/addressbook/addresssettingsbase.ui new file mode 100644 index 0000000..bd3b85b --- a/dev/null +++ b/core/pim/addressbook/addresssettingsbase.ui @@ -0,0 +1,170 @@ + +AddressSettingsBase +/********************************************************************** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +** $Id$ +** +**********************************************************************/ + + QDialog + + name + AddressSettingsBase + + + geometry + + 0 + 0 + 244 + 207 + + + + caption + Arrange Edit Fields + + + layoutMargin + + + layoutSpacing + + + + margin + 6 + + + spacing + 6 + + + QListBox + + name + fieldListBox + + + + QLabel + + name + lblExplain + + + sizePolicy + + 1 + 1 + + + + frameShape + MShape + + + frameShadow + MShadow + + + text + Select the field order: + + + alignment + AlignTop|AlignLeft + + + hAlign + + + vAlign + + + + QPushButton + + name + upButton + + + text + Up + + + autoRepeat + true + + + + QPushButton + + name + downButton + + + text + Down + + + autoRepeat + true + + + + + name + Spacer2 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + + upButton + clicked() + AddressSettingsBase + itemUp() + + + downButton + clicked() + AddressSettingsBase + itemDown() + + itemUp() + itemDown() + + diff --git a/core/pim/addressbook/main.cpp b/core/pim/addressbook/main.cpp new file mode 100644 index 0000000..2ea1819 --- a/dev/null +++ b/core/pim/addressbook/main.cpp @@ -0,0 +1,41 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qt Palmtop Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "addressbook.h" + +#include +#include +#include + +int main( int argc, char ** argv ) +{ + QPEApplication a( argc, argv ); + + AddressbookWindow mw; + QObject::connect( &a, SIGNAL( flush() ), &mw, SLOT( flush() ) ); + QObject::connect( &a, SIGNAL( reload() ), &mw, SLOT( reload() ) ); + QObject::connect( &a, SIGNAL( appMessage(const QCString &, const QByteArray &) ), + &mw, SLOT( appMessage(const QCString &, const QByteArray &) ) ); + + mw.setCaption( AddressbookWindow::tr("Contacts") ); + a.showMainDocumentWidget(&mw); + + return a.exec(); +} diff --git a/core/pim/addressbook/qpe-addressbook.control b/core/pim/addressbook/qpe-addressbook.control new file mode 100644 index 0000000..cca98f3 --- a/dev/null +++ b/core/pim/addressbook/qpe-addressbook.control @@ -0,0 +1,9 @@ +Files: bin/addressbook apps/Applications/addressbook.desktop +Priority: optional +Section: qpe/applications +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: Contacts + A simple addressbook for the Qtopia environment. diff --git a/core/pim/datebook/.cvsignore b/core/pim/datebook/.cvsignore new file mode 100644 index 0000000..4ba477d --- a/dev/null +++ b/core/pim/datebook/.cvsignore @@ -0,0 +1,12 @@ +moc_* +Makefile +dateentry.h +datebookdayheader.h +dateentry.cpp +datebookdayheader.cpp +datebookweekheader.cpp +datebookweekheader.h +datebooksettingsbase.h +datebooksettingsbase.cpp +repeatentrybase.cpp +repeatentrybase.h diff --git a/core/pim/datebook/Makefile.in b/core/pim/datebook/Makefile.in new file mode 100644 index 0000000..bdc69dc --- a/dev/null +++ b/core/pim/datebook/Makefile.in @@ -0,0 +1,385 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = $(QPEDIR)/bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = datebook +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = datebookday.h \ + datebook.h \ + dateentryimpl.h \ + datebookdayheaderimpl.h \ + datebooksettings.h \ + datebookweek.h \ + datebookweekheaderimpl.h \ + repeatentry.h +SOURCES = main.cpp \ + datebookday.cpp \ + datebook.cpp \ + dateentryimpl.cpp \ + datebookdayheaderimpl.cpp \ + datebooksettings.cpp \ + datebookweek.cpp \ + datebookweekheaderimpl.cpp \ + repeatentry.cpp +OBJECTS = main.o \ + datebookday.o \ + datebook.o \ + dateentryimpl.o \ + datebookdayheaderimpl.o \ + datebooksettings.o \ + datebookweek.o \ + datebookweekheaderimpl.o \ + repeatentry.o \ + dateentry.o \ + datebookdayheader.o \ + datebooksettingsbase.o \ + datebookweekheader.o \ + repeatentrybase.o +INTERFACES = dateentry.ui \ + datebookdayheader.ui \ + datebooksettingsbase.ui \ + datebookweekheader.ui \ + repeatentrybase.ui +UICDECLS = dateentry.h \ + datebookdayheader.h \ + datebooksettingsbase.h \ + datebookweekheader.h \ + repeatentrybase.h +UICIMPLS = dateentry.cpp \ + datebookdayheader.cpp \ + datebooksettingsbase.cpp \ + datebookweekheader.cpp \ + repeatentrybase.cpp +SRCMOC = moc_datebookday.cpp \ + moc_datebook.cpp \ + moc_dateentryimpl.cpp \ + moc_datebookdayheaderimpl.cpp \ + moc_datebookweek.cpp \ + moc_datebookweekheaderimpl.cpp \ + moc_repeatentry.cpp \ + moc_dateentry.cpp \ + moc_datebookdayheader.cpp \ + moc_datebooksettingsbase.cpp \ + moc_datebookweekheader.cpp \ + moc_repeatentrybase.cpp +OBJMOC = moc_datebookday.o \ + moc_datebook.o \ + moc_dateentryimpl.o \ + moc_datebookdayheaderimpl.o \ + moc_datebookweek.o \ + moc_datebookweekheaderimpl.o \ + moc_repeatentry.o \ + moc_dateentry.o \ + moc_datebookdayheader.o \ + moc_datebooksettingsbase.o \ + moc_datebookweekheader.o \ + moc_repeatentrybase.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake datebook.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +main.o: main.cpp \ + datebook.h \ + $(QPEDIR)/include/qpe/datebookdb.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/qpeapplication.h + +datebookday.o: datebookday.cpp \ + datebookday.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + datebookdayheaderimpl.h \ + datebookdayheader.h \ + $(QPEDIR)/include/qpe/datebookdb.h \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/timestring.h \ + $(QPEDIR)/include/qpe/qpedebug.h + +datebook.o: datebook.cpp \ + datebook.h \ + $(QPEDIR)/include/qpe/datebookdb.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + datebookday.h \ + datebooksettings.h \ + datebooksettingsbase.h \ + datebookweek.h \ + dateentryimpl.h \ + dateentry.h \ + $(QPEDIR)/include/qpe/datebookmonth.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/qpedebug.h \ + $(QPEDIR)/include/qpe/finddialog.h \ + $(QPEDIR)/include/qpe/ir.h \ + $(QPEDIR)/include/qpe/qpemenubar.h \ + $(QPEDIR)/include/qpe/qpemessagebox.h \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/sound.h \ + $(QPEDIR)/include/qpe/timestring.h \ + $(QPEDIR)/include/qpe/qpetoolbar.h \ + $(QPEDIR)/include/qpe/tzselect.h \ + $(QPEDIR)/include/qpe/xmlreader.h + +dateentryimpl.o: dateentryimpl.cpp \ + dateentryimpl.h \ + dateentry.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + repeatentry.h \ + repeatentrybase.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/categoryselect.h \ + $(QPEDIR)/include/qpe/datebookmonth.h \ + $(QPEDIR)/include/qpe/global.h \ + $(QPEDIR)/include/qpe/timeconversion.h \ + $(QPEDIR)/include/qpe/timestring.h \ + $(QPEDIR)/include/qpe/tzselect.h + +datebookdayheaderimpl.o: datebookdayheaderimpl.cpp \ + datebookdayheaderimpl.h \ + datebookdayheader.h \ + $(QPEDIR)/include/qpe/datebookmonth.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/timestring.h + +datebooksettings.o: datebooksettings.cpp \ + datebooksettings.h \ + datebooksettingsbase.h \ + $(QPEDIR)/include/qpe/qpeapplication.h + +datebookweek.o: datebookweek.cpp \ + datebookweek.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + datebookweekheaderimpl.h \ + datebookweekheader.h \ + $(QPEDIR)/include/qpe/calendar.h \ + $(QPEDIR)/include/qpe/datebookdb.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/timestring.h + +datebookweekheaderimpl.o: datebookweekheaderimpl.cpp \ + datebookweekheaderimpl.h \ + datebookweekheader.h + +repeatentry.o: repeatentry.cpp \ + repeatentry.h \ + repeatentrybase.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/datebookmonth.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/timestring.h + +dateentry.h: dateentry.ui + $(UIC) dateentry.ui -o $(INTERFACE_DECL_PATH)/dateentry.h + +dateentry.cpp: dateentry.ui + $(UIC) dateentry.ui -i dateentry.h -o dateentry.cpp + +datebookdayheader.h: datebookdayheader.ui + $(UIC) datebookdayheader.ui -o $(INTERFACE_DECL_PATH)/datebookdayheader.h + +datebookdayheader.cpp: datebookdayheader.ui + $(UIC) datebookdayheader.ui -i datebookdayheader.h -o datebookdayheader.cpp + +datebooksettingsbase.h: datebooksettingsbase.ui + $(UIC) datebooksettingsbase.ui -o $(INTERFACE_DECL_PATH)/datebooksettingsbase.h + +datebooksettingsbase.cpp: datebooksettingsbase.ui + $(UIC) datebooksettingsbase.ui -i datebooksettingsbase.h -o datebooksettingsbase.cpp + +datebookweekheader.h: datebookweekheader.ui + $(UIC) datebookweekheader.ui -o $(INTERFACE_DECL_PATH)/datebookweekheader.h + +datebookweekheader.cpp: datebookweekheader.ui + $(UIC) datebookweekheader.ui -i datebookweekheader.h -o datebookweekheader.cpp + +repeatentrybase.h: repeatentrybase.ui + $(UIC) repeatentrybase.ui -o $(INTERFACE_DECL_PATH)/repeatentrybase.h + +repeatentrybase.cpp: repeatentrybase.ui + $(UIC) repeatentrybase.ui -i repeatentrybase.h -o repeatentrybase.cpp + +dateentry.o: dateentry.cpp + +datebookdayheader.o: datebookdayheader.cpp + +datebooksettingsbase.o: datebooksettingsbase.cpp + +datebookweekheader.o: datebookweekheader.cpp + +repeatentrybase.o: repeatentrybase.cpp + +moc_datebookday.o: moc_datebookday.cpp \ + datebookday.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h + +moc_datebook.o: moc_datebook.cpp \ + datebook.h \ + $(QPEDIR)/include/qpe/datebookdb.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h + +moc_dateentryimpl.o: moc_dateentryimpl.cpp \ + dateentryimpl.h \ + dateentry.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h + +moc_datebookdayheaderimpl.o: moc_datebookdayheaderimpl.cpp \ + datebookdayheaderimpl.h \ + datebookdayheader.h + +moc_datebookweek.o: moc_datebookweek.cpp \ + datebookweek.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h + +moc_datebookweekheaderimpl.o: moc_datebookweekheaderimpl.cpp \ + datebookweekheaderimpl.h \ + datebookweekheader.h + +moc_repeatentry.o: moc_repeatentry.cpp \ + repeatentry.h \ + repeatentrybase.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h + +moc_dateentry.o: moc_dateentry.cpp \ + dateentry.h + +moc_datebookdayheader.o: moc_datebookdayheader.cpp \ + datebookdayheader.h + +moc_datebooksettingsbase.o: moc_datebooksettingsbase.cpp \ + datebooksettingsbase.h + +moc_datebookweekheader.o: moc_datebookweekheader.cpp \ + datebookweekheader.h + +moc_repeatentrybase.o: moc_repeatentrybase.cpp \ + repeatentrybase.h + +moc_datebookday.cpp: datebookday.h + $(MOC) datebookday.h -o moc_datebookday.cpp + +moc_datebook.cpp: datebook.h + $(MOC) datebook.h -o moc_datebook.cpp + +moc_dateentryimpl.cpp: dateentryimpl.h + $(MOC) dateentryimpl.h -o moc_dateentryimpl.cpp + +moc_datebookdayheaderimpl.cpp: datebookdayheaderimpl.h + $(MOC) datebookdayheaderimpl.h -o moc_datebookdayheaderimpl.cpp + +moc_datebookweek.cpp: datebookweek.h + $(MOC) datebookweek.h -o moc_datebookweek.cpp + +moc_datebookweekheaderimpl.cpp: datebookweekheaderimpl.h + $(MOC) datebookweekheaderimpl.h -o moc_datebookweekheaderimpl.cpp + +moc_repeatentry.cpp: repeatentry.h + $(MOC) repeatentry.h -o moc_repeatentry.cpp + +moc_dateentry.cpp: dateentry.h + $(MOC) dateentry.h -o moc_dateentry.cpp + +moc_datebookdayheader.cpp: datebookdayheader.h + $(MOC) datebookdayheader.h -o moc_datebookdayheader.cpp + +moc_datebooksettingsbase.cpp: datebooksettingsbase.h + $(MOC) datebooksettingsbase.h -o moc_datebooksettingsbase.cpp + +moc_datebookweekheader.cpp: datebookweekheader.h + $(MOC) datebookweekheader.h -o moc_datebookweekheader.cpp + +moc_repeatentrybase.cpp: repeatentrybase.h + $(MOC) repeatentrybase.h -o moc_repeatentrybase.cpp + + diff --git a/core/pim/datebook/datebook.cpp b/core/pim/datebook/datebook.cpp new file mode 100644 index 0000000..6ec6cc2 --- a/dev/null +++ b/core/pim/datebook/datebook.cpp @@ -0,0 +1,854 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +** $Id$ +** +**********************************************************************/ + +#include "datebook.h" +#include "datebookday.h" +#include "datebooksettings.h" +#include "datebookweek.h" +#include "dateentryimpl.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define DAY 1 +#define WEEK 2 +#define MONTH 3 + + +DateBook::DateBook( QWidget *parent, const char *, WFlags f ) + : QMainWindow( parent, "datebook", f ), + aPreset( FALSE ), + presetTime( -1 ), + startTime( 8 ), // an acceptable default + syncing(FALSE), + inSearch(FALSE) +{ + QTime t; + t.start(); + db = new DateBookDB; + qDebug("loading db t=%d", t.elapsed() ); + loadSettings(); + setCaption( tr("Calendar") ); + setIcon( Resource::loadPixmap( "datebook_icon" ) ); + + setToolBarsMovable( FALSE ); + + QPEToolBar *bar = new QPEToolBar( this ); + bar->setHorizontalStretchable( TRUE ); + + QPEMenuBar *mb = new QPEMenuBar( bar ); + mb->setMargin( 0 ); + + QPEToolBar *sub_bar = new QPEToolBar(this); + + QPopupMenu *view = new QPopupMenu( this ); + QPopupMenu *settings = new QPopupMenu( this ); + + mb->insertItem( tr( "View" ), view ); + mb->insertItem( tr( "Settings" ), settings ); + + QActionGroup *g = new QActionGroup( this ); + g->setExclusive( TRUE ); + + QAction *a = new QAction( tr( "New" ), Resource::loadPixmap( "new" ), + QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( fileNew() ) ); + a->addTo( sub_bar ); + + a = new QAction( tr( "Day" ), Resource::loadPixmap( "day" ), QString::null, 0, g, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( viewDay() ) ); + a->addTo( sub_bar ); + a->addTo( view ); + a->setToggleAction( TRUE ); + a->setOn( TRUE ); + dayAction = a; + a = new QAction( tr( "Week" ), Resource::loadPixmap( "week" ), QString::null, 0, g, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( viewWeek() ) ); + a->addTo( sub_bar ); + a->addTo( view ); + a->setToggleAction( TRUE ); + weekAction = a; + a = new QAction( tr( "Month" ), Resource::loadPixmap( "month" ), QString::null, 0, g, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( viewMonth() ) ); + a->addTo( sub_bar ); + a->addTo( view ); + a->setToggleAction( TRUE ); + monthAction = a; + + a = new QAction( tr( "Find" ), Resource::loadPixmap( "mag" ), QString::null, 0, g, 0 ); + connect( a, SIGNAL(activated()), this, SLOT(slotFind()) ); + a->addTo( sub_bar ); + + a = new QAction( tr( "Today" ), QString::null, 0, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( slotToday() ) ); + a->addTo( view ); + + a = new QAction( tr( "Alarm and Start Time..." ), QString::null, 0, 0 ); + connect( a, SIGNAL( activated() ), this, SLOT( slotSettings() ) ); + a->addTo( settings ); + + views = new QWidgetStack( this ); + setCentralWidget( views ); + + dayView = 0; + weekView = 0; + monthView = 0; + + viewDay(); + connect( qApp, SIGNAL(clockChanged(bool)), + this, SLOT(changeClock(bool)) ); + connect( qApp, SIGNAL(weekChanged(bool)), + this, SLOT(changeWeek(bool)) ); + +#if defined(Q_WS_QWS) && !defined(QT_NO_COP) + connect( qApp, SIGNAL(appMessage(const QCString&, const QByteArray&)), + this, SLOT(appMessage(const QCString&, const QByteArray&)) ); +#endif + + // listen on QPE/System +#if defined(Q_WS_QWS) +#if !defined(QT_NO_COP) + QCopChannel *channel = new QCopChannel( "QPE/System", this ); + connect( channel, SIGNAL(received(const QCString&, const QByteArray&)), + this, SLOT(receive(const QCString&, const QByteArray&)) ); +#endif +#endif + + qDebug("done t=%d", t.elapsed() ); + +} + +void DateBook::receive( const QCString &msg, const QByteArray &data ) +{ + QDataStream stream( data, IO_ReadOnly ); + if ( msg == "timeChange(QString)" ) { + // update active view! + if ( dayAction->isOn() ) + viewDay(); + else if ( weekAction->isOn() ) + viewWeek(); + else if ( monthAction->isOn() ) + viewMonth(); + } +} + +DateBook::~DateBook() +{ +} + +void DateBook::slotSettings() +{ + DateBookSettings frmSettings( ampm, this ); + frmSettings.setStartTime( startTime ); + frmSettings.setAlarmPreset( aPreset, presetTime ); +#if defined (Q_WS_QWS) || defined(_WS_QWS_) + frmSettings.showMaximized(); +#endif + + if ( frmSettings.exec() ) { + aPreset = frmSettings.alarmPreset(); + presetTime = frmSettings.presetTime(); + startTime = frmSettings.startTime(); + if ( dayView ) + dayView->setStartViewTime( startTime ); + if ( weekView ) + weekView->setStartViewTime( startTime ); + saveSettings(); + + // make the change obvious + if ( views->visibleWidget() ) { + if ( views->visibleWidget() == dayView ) + dayView->redraw(); + else if ( views->visibleWidget() == weekView ) + weekView->redraw(); + } + } +} + +void DateBook::fileNew() +{ + slotNewEventFromKey(""); +} + +QString DateBook::checkEvent(const Event &e) +{ + /* check if overlaps with itself */ + bool checkFailed = FALSE; + + /* check the next 12 repeats. should catch most problems */ + QDate current_date = e.start().date(); + Event previous = e; + for(int i = 0; i < 12; i++) + { + QDateTime next; + if (!nextOccurance(previous, current_date.addDays(1), next)) { + break; // no more repeats + } + if(next < previous.end()) { + checkFailed = TRUE; + break; + } + current_date = next.date(); + } + + if(checkFailed) + return tr("Event duration is potentially longer\n" + "than interval between repeats."); + + return QString::null; +} + +QDate DateBook::currentDate() +{ + QDate d = QDate::currentDate(); + + if ( dayView && views->visibleWidget() == dayView ) { + d = dayView->date(); + } else if ( weekView && views->visibleWidget() == weekView ) { + d = weekView->date(); + } else if ( monthView && views->visibleWidget() == monthView ) { + d = monthView->selectedDate(); + } + + return d; +} + +void DateBook::viewDay() +{ + initDay(); + dayAction->setOn( TRUE ); + QDate d = currentDate(); + dayView->setDate( d ); + views->raiseWidget( dayView ); + dayView->redraw(); +} + +void DateBook::viewWeek() +{ + initWeek(); + weekAction->setOn( TRUE ); + QDate d = currentDate(); + weekView->setDate( d ); + views->raiseWidget( weekView ); + weekView->redraw(); +} + +void DateBook::viewMonth() +{ + initMonth(); + monthAction->setOn( TRUE ); + QDate d = currentDate(); + monthView->setDate( d.year(), d.month(), d.day() ); + views->raiseWidget( monthView ); + monthView->redraw(); +} + +void DateBook::editEvent( const Event &e ) +{ + if (syncing) { + QMessageBox::warning( this, tr("Calendar"), + tr( "Can not edit data, currently syncing") ); + return; + } + + // workaround added for text input. + QDialog editDlg( this, 0, TRUE ); + DateEntry *entry; + editDlg.setCaption( tr("Edit Event") ); + QVBoxLayout *vb = new QVBoxLayout( &editDlg ); + QScrollView *sv = new QScrollView( &editDlg, "scrollview" ); + sv->setResizePolicy( QScrollView::AutoOneFit ); + // KLUDGE!!! + sv->setHScrollBarMode( QScrollView::AlwaysOff ); + vb->addWidget( sv ); + entry = new DateEntry( onMonday, e, ampm, &editDlg, "editor" ); + entry->timezone->setEnabled( FALSE ); + sv->addChild( entry ); + +#if defined(Q_WS_QWS) || defined(_WS_QWS_) + editDlg.showMaximized(); +#endif + while (editDlg.exec() ) { + Event newEv = entry->event(); + QString error = checkEvent(newEv); + if (!error.isNull()) { + if (QMessageBox::warning(this, "error box", + error, "Fix it", "Continue", 0, 0, 1) == 0) + continue; + } + db->editEvent(e, newEv); + emit newEvent(); + break; + } +} + +void DateBook::removeEvent( const Event &e ) +{ + if (syncing) { + QMessageBox::warning( this, tr("Calendar"), + tr( "Can not edit data, currently syncing") ); + return; + } + + QString strName = e.description(); + + if ( !QPEMessageBox::confirmDelete( this, tr( "Calendar" ),strName ) ) + return; + + db->removeEvent( e ); + if ( views->visibleWidget() == dayView && dayView ) + dayView->redraw(); +} + +void DateBook::addEvent( const Event &e ) +{ + QDate d = e.start().date(); + initDay(); + dayView->setDate( d ); +} + +void DateBook::showDay( int year, int month, int day ) +{ + initDay(); + dayView->setDate( year, month, day ); + views->raiseWidget( dayView ); + dayAction->setOn( TRUE ); +} + +void DateBook::initDay() +{ + if ( !dayView ) { + dayView = new DateBookDay( ampm, onMonday, db, views, "day view" ); + views->addWidget( dayView, DAY ); + dayView->setStartViewTime( startTime ); + connect( this, SIGNAL( newEvent() ), + dayView, SLOT( redraw() ) ); + connect( dayView, SIGNAL( newEvent() ), + this, SLOT( fileNew() ) ); + connect( dayView, SIGNAL( removeEvent( const Event & ) ), + this, SLOT( removeEvent( const Event & ) ) ); + connect( dayView, SIGNAL( editEvent( const Event & ) ), + this, SLOT( editEvent( const Event & ) ) ); + connect( dayView, SIGNAL( beamEvent( const Event & ) ), + this, SLOT( beamEvent( const Event & ) ) ); + connect( dayView, SIGNAL(sigNewEvent(const QString &)), + this, SLOT(slotNewEventFromKey(const QString &)) ); + } +} + +void DateBook::initWeek() +{ + if ( !weekView ) { + weekView = new DateBookWeek( ampm, onMonday, db, views, "week view" ); + weekView->setStartViewTime( startTime ); + views->addWidget( weekView, WEEK ); + connect( weekView, SIGNAL( showDate( int, int, int ) ), + this, SLOT( showDay( int, int, int ) ) ); + connect( this, SIGNAL( newEvent() ), + weekView, SLOT( redraw() ) ); + } + //But also get it right: the year that we display can be different + //from the year of the current date. So, first find the year + //number of the current week. + + int yearNumber, totWeeks; + calcWeek( currentDate(), totWeeks, yearNumber, onMonday ); + + QDate d = QDate( yearNumber, 12, 31 ); + calcWeek( d, totWeeks, yearNumber, onMonday ); + + while ( totWeeks == 1 ) { + d = d.addDays( -1 ); + calcWeek( d, totWeeks, yearNumber, onMonday ); + } + if ( totWeeks != weekView->totalWeeks() ) + weekView->setTotalWeeks( totWeeks ); +} + +void DateBook::initMonth() +{ + if ( !monthView ) { + monthView = new DateBookMonth( views, "month view", FALSE, db ); + views->addWidget( monthView, MONTH ); + connect( monthView, SIGNAL( dateClicked( int, int, int ) ), + this, SLOT( showDay( int, int, int ) ) ); + connect( this, SIGNAL( newEvent() ), + monthView, SLOT( redraw() ) ); + qApp->processEvents(); + } +} + +void DateBook::loadSettings() +{ + { + Config config( "qpe" ); + config.setGroup("Time"); + ampm = config.readBoolEntry( "AMPM", TRUE ); + onMonday = config.readBoolEntry( "MONDAY" ); + } + + { + Config config("DateBook"); + config.setGroup("Main"); + startTime = config.readNumEntry("startviewtime", 8); + aPreset = config.readBoolEntry("alarmpreset"); + presetTime = config.readNumEntry("presettime"); + } +} + +void DateBook::saveSettings() +{ + Config config( "qpe" ); + Config configDB( "DateBook" ); + configDB.setGroup( "Main" ); + configDB.writeEntry("startviewtime",startTime); + configDB.writeEntry("alarmpreset",aPreset); + configDB.writeEntry("presettime",presetTime); +} + +void DateBook::appMessage(const QCString& msg, const QByteArray& data) +{ + bool needShow = FALSE; + if ( msg == "alarm(QDateTime,int)" ) { + QDataStream ds(data,IO_ReadOnly); + QDateTime when; int warn; + ds >> when >> warn; + + // check to make it's okay to continue, + // this is the case that the time was set ahead, and + // we are forced given a stale alarm... + QDateTime current = QDateTime::currentDateTime(); + if ( current.time().hour() != when.time().hour() + && current.time().minute() != when.time().minute() ) + return; + + QValueList list = db->getEffectiveEvents(when.addSecs(warn*60)); + if ( list.count() > 0 ) { + QString msg; + bool bSound = FALSE; + int stopTimer = 0; + bool found = FALSE; + for ( QValueList::ConstIterator it=list.begin(); + it!=list.end(); ++it ) { + if ( (*it).event().hasAlarm() ) { + found = TRUE; + msg += "
" + (*it).description() + "" + + "
" + (*it).location() + "
" + + TimeString::dateString((*it).event().start(),ampm) + + (warn + ? tr(" (in " + QString::number(warn) + + tr(" minutes)")) + : QString("")) + + "
" + + (*it).notes() + "
"; + if ( (*it).event().alarmSound() != Event::Silent ) { + bSound = TRUE; + } + } + } + if ( found ) { + if ( bSound ) { + Sound::soundAlarm(); + stopTimer = startTimer( 5000 ); + } + + QDialog dlg( this, 0, TRUE ); + QVBoxLayout *vb = new QVBoxLayout( &dlg ); + QScrollView *view = new QScrollView( &dlg, "scrollView"); + view->setResizePolicy( QScrollView::AutoOneFit ); + vb->addWidget( view ); + QLabel *lblMsg = new QLabel( msg, &dlg ); + view->addChild( lblMsg ); + QPushButton *cmdOk = new QPushButton( tr("OK"), &dlg ); + connect( cmdOk, SIGNAL(clicked()), &dlg, SLOT(accept()) ); + vb->addWidget( cmdOk ); + +#if defined(Q_WS_QWS) || defined(_WS_QWS_) + dlg.showMaximized(); +#endif + needShow = dlg.exec(); + + if ( bSound ) + killTimer( stopTimer ); + } + } + } else if ( msg == "nextView()" ) { + QWidget* cur = views->visibleWidget(); + if ( cur ) { + if ( cur == dayView ) + viewWeek(); + else if ( cur == weekView ) + viewMonth(); + else if ( cur == monthView ) + viewDay(); + needShow = TRUE; + } + } + if ( needShow ) { +#if defined(Q_WS_QWS) || defined(_WS_QWS_) + showMaximized(); +#else + show(); +#endif + raise(); + QPEApplication::setKeepRunning(); + setActiveWindow(); + } +} + +void DateBook::reload() +{ + db->reload(); + if ( dayAction->isOn() ) + viewDay(); + else if ( weekAction->isOn() ) + viewWeek(); + else if ( monthAction->isOn() ) + viewMonth(); + syncing = FALSE; +} + +void DateBook::flush() +{ + syncing = TRUE; + db->save(); +} + +void DateBook::timerEvent( QTimerEvent *e ) +{ + static int stop = 0; + if ( stop < 10 ) { + Sound::soundAlarm(); + stop++; + } else { + stop = 0; + killTimer( e->timerId() ); + } +} + +void DateBook::changeClock( bool newClock ) +{ + ampm = newClock; + // repaint the affected objects... + if (dayView) dayView->redraw(); + if (weekView) weekView->redraw(); +} + +void DateBook::changeWeek( bool m ) +{ + /* no need to redraw, each widget catches. Do need to + store though for widgets we haven't made yet */ + onMonday = m; +} + +void DateBook::slotToday() +{ + // we need to view today + QDate dt = QDate::currentDate(); + showDay( dt.year(), dt.month(), dt.day() ); +} + +void DateBook::closeEvent( QCloseEvent *e ) +{ + if(syncing) { + /* no need to save, did that at flush */ + e->accept(); + return; + } + + // save settings will generate it's own error messages, no + // need to do checking ourselves. + saveSettings(); + if ( db->save() ) + e->accept(); + else { + if ( QMessageBox::critical( this, tr( "Out of space" ), + tr("Calendar was unable to save\n" + "your changes.\n" + "Free up some space and try again.\n" + "\nQuit anyway?"), + QMessageBox::Yes|QMessageBox::Escape, + QMessageBox::No|QMessageBox::Default ) + != QMessageBox::No ) + e->accept(); + else + e->ignore(); + } +} + +// Entering directly from the "keyboard" +void DateBook::slotNewEventFromKey( const QString &str ) +{ + if (syncing) { + QMessageBox::warning( this, tr("Calendar"), + tr( "Can not edit data, currently syncing") ); + return; + } + + // We get to here from a key pressed in the Day View + // So we can assume some things. We want the string + // passed in to be part of the description. + QDateTime start, end; + if ( views->visibleWidget() == dayView ) { + dayView->selectedDates( start, end ); + } else if ( views->visibleWidget() == monthView ) { + QDate d = monthView->selectedDate(); + start = end = d; + start.setTime( QTime( 10, 0 ) ); + end.setTime( QTime( 12, 0 ) ); + } else if ( views->visibleWidget() == weekView ) { + QDate d = weekView->date(); + start = end = d; + start.setTime( QTime( 10, 0 ) ); + end.setTime( QTime( 12, 0 ) ); + } + + // argh! This really needs to be encapsulated in a class + // or function. + QDialog newDlg( this, 0, TRUE ); + newDlg.setCaption( DateEntryBase::tr("New Event") ); + DateEntry *e; + QVBoxLayout *vb = new QVBoxLayout( &newDlg ); + QScrollView *sv = new QScrollView( &newDlg ); + sv->setResizePolicy( QScrollView::AutoOneFit ); + sv->setFrameStyle( QFrame::NoFrame ); + sv->setHScrollBarMode( QScrollView::AlwaysOff ); + vb->addWidget( sv ); + + Event ev; + ev.setDescription( str ); + // When the new gui comes in, change this... + ev.setLocation( tr("(Unknown)") ); + ev.setStart( start ); + ev.setEnd( end ); + + e = new DateEntry( onMonday, ev, ampm, &newDlg ); + e->setAlarmEnabled( aPreset, presetTime, Event::Loud ); + sv->addChild( e ); +#if defined(Q_WS_QWS) || defined(_WS_QWS_) + newDlg.showMaximized(); +#endif + while (newDlg.exec()) { + ev = e->event(); + ev.assignUid(); + QString error = checkEvent( ev ); + if ( !error.isNull() ) { + if ( QMessageBox::warning( this, tr("Error!"), + error, tr("Fix it"), tr("Continue"), 0, 0, 1 ) == 0 ) + continue; + } + db->addEvent( ev ); + emit newEvent(); + break; + } +} + +void DateBook::setDocument( const QString &filename ) +{ + if ( filename.find(".vcs") != int(filename.length()) - 4 ) return; + + QValueList tl = Event::readVCalendar( filename ); + for( QValueList::Iterator it = tl.begin(); it != tl.end(); ++it ) { + db->addEvent( *it ); + } +} + +static const char * beamfile = "/tmp/obex/event.vcs"; + +void DateBook::beamEvent( const Event &e ) +{ + qDebug("trying to beamn"); + unlink( beamfile ); // delete if exists + mkdir("/tmp/obex/", 0755); + Event::writeVCalendar( beamfile, e ); + Ir *ir = new Ir( this ); + connect( ir, SIGNAL( done( Ir * ) ), this, SLOT( beamDone( Ir * ) ) ); + QString description = e.description(); + ir->send( beamfile, description, "text/x-vCalendar" ); +} + +void DateBook::beamDone( Ir *ir ) +{ + delete ir; + unlink( beamfile ); +} + +void DateBook::slotFind() +{ + // move it to the day view... + viewDay(); + FindDialog frmFind( "Calendar", this ); + frmFind.setUseDate( true ); + frmFind.setDate( currentDate() ); + QObject::connect( &frmFind, + SIGNAL(signalFindClicked(const QString&, const QDate&, + bool, bool, int)), + this, + SLOT(slotDoFind(const QString&, const QDate&, + bool, bool, int)) ); + QObject::connect( this, + SIGNAL(signalNotFound()), + &frmFind, + SLOT(slotNotFound()) ); + QObject::connect( this, + SIGNAL(signalWrapAround()), + &frmFind, + SLOT(slotWrapAround()) ); + frmFind.exec(); + inSearch = false; +} + +bool catComp( QArray cats, int category ) +{ + bool returnMe; + int i, + count; + + count = int(cats.count()); + returnMe = false; + if ( (category == -1 && count == 0) || category == -2 ) + returnMe = true; + else { + for ( i = 0; i < count; i++ ) { + if ( category == cats[i] ) { + returnMe = true; + break; + } + } + } + return returnMe; +} + + +void DateBook::slotDoFind( const QString& txt, const QDate &dt, + bool caseSensitive, bool /*backwards*/, + int category ) +{ + QDateTime dtEnd( QDate(3001, 1, 1), QTime(0, 0, 0) ), + next; + + QRegExp r( txt ); + r.setCaseSensitive( caseSensitive ); + + + static Event rev, + nonrev; + if ( !inSearch ) { + rev.setStart( QDateTime(QDate(1960, 1, 1), QTime(0, 0, 0)) ); + nonrev.setStart( rev.start() ); + inSearch = true; + } + static QDate searchDate = dt; + static bool wrapAround = true; + bool candidtate; + candidtate = false; + + QValueList repeats = db->getRawRepeats(); + + // find the candidate for the first repeat that matches... + QValueListConstIterator it; + QDate start = dt; + for ( it = repeats.begin(); it != repeats.end(); ++it ) { + if ( catComp( (*it).categories(), category ) ) { + while ( nextOccurance( *it, start, next ) ) { + if ( next < dtEnd ) { + if ( (*it).match( r ) && !(next <= rev.start()) ) { + rev = *it; + dtEnd = next; + rev.setStart( next ); + candidtate = true; + wrapAround = true; + start = dt; + break; + } else + start = next.date().addDays( 1 ); + } + } + } + } + + // now the for first non repeat... + QValueList nonRepeats = db->getNonRepeatingEvents( dt, dtEnd.date() ); + qHeapSort( nonRepeats.begin(), nonRepeats.end() ); + for ( it = nonRepeats.begin(); it != nonRepeats.end(); ++it ) { + if ( catComp( (*it).categories(), category ) ) { + if ( (*it).start() < dtEnd ) { + if ( (*it).match( r ) && !(*it <= nonrev) ) { + nonrev = *it; + dtEnd = nonrev.start(); + candidtate = true; + wrapAround = true; + break; + } + } + } + } + if ( candidtate ) { + dayView->setStartViewTime( dtEnd.time().hour() ); + dayView->setDate( dtEnd.date().year(), dtEnd.date().month(), + dtEnd.date().day() ); + } else { + if ( wrapAround ) { + emit signalWrapAround(); + rev.setStart( QDateTime(QDate(1960, 1, 1), QTime(0, 0, 0)) ); + nonrev.setStart( rev.start() ); + } else + emit signalNotFound(); + wrapAround = !wrapAround; + } +} diff --git a/core/pim/datebook/datebook.h b/core/pim/datebook/datebook.h new file mode 100644 index 0000000..44627bb --- a/dev/null +++ b/core/pim/datebook/datebook.h @@ -0,0 +1,111 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef DATEBOOK_H +#define DATEBOOK_H + +#include + +#include + +class QAction; +class QWidgetStack; +class DateBookDay; +class DateBookWeek; +class DateBookMonth; +class Event; +class QDate; +class Ir; + +class DateBook : public QMainWindow +{ + Q_OBJECT + +public: + DateBook( QWidget *parent = 0, const char *name = 0, WFlags f = 0 ); + ~DateBook(); + +signals: + void newEvent(); + void signalNotFound(); + void signalWrapAround(); + +protected: + QDate currentDate(); + void timerEvent( QTimerEvent *e ); + void closeEvent( QCloseEvent *e ); + +public slots: + void flush(); + void reload(); + +private slots: + void fileNew(); + void slotSettings(); + void slotToday(); // view today + void changeClock( bool newClock ); + void changeWeek( bool newDay ); + void appMessage(const QCString& msg, const QByteArray& data); + // handle key events in the day view... + void slotNewEventFromKey( const QString &str ); + void slotFind(); + void slotDoFind( const QString &, const QDate &, bool, bool, int ); + + void viewDay(); + void viewWeek(); + void viewMonth(); + + void showDay( int y, int m, int d ); + + void editEvent( const Event &e ); + void removeEvent( const Event &e ); + + void receive( const QCString &msg, const QByteArray &data ); + void setDocument( const QString & ); + void beamEvent( const Event &e ); + void beamDone( Ir *ir ); + +private: + void addEvent( const Event &e ); + void initDay(); + void initWeek(); + void initMonth(); + void loadSettings(); + void saveSettings(); + +private: + DateBookDB *db; + QWidgetStack *views; + DateBookDay *dayView; + DateBookWeek *weekView; + DateBookMonth *monthView; + QAction *dayAction, *weekAction, *monthAction; + bool aPreset; // have everything set to alarm? + int presetTime; // the standard time for the alarm + int startTime; + bool ampm; + bool onMonday; + + bool syncing; + bool inSearch; + + QString checkEvent(const Event &); +}; + +#endif diff --git a/core/pim/datebook/datebook.pro b/core/pim/datebook/datebook.pro new file mode 100644 index 0000000..17c02ec --- a/dev/null +++ b/core/pim/datebook/datebook.pro @@ -0,0 +1,36 @@ +TEMPLATE = app +CONFIG += qt warn_on release +DESTDIR = $(QPEDIR)/bin + +HEADERS = datebookday.h \ + datebook.h \ + dateentryimpl.h \ + datebookdayheaderimpl.h \ + datebooksettings.h \ + datebookweek.h \ + datebookweekheaderimpl.h \ + repeatentry.h + +SOURCES = main.cpp \ + datebookday.cpp \ + datebook.cpp \ + dateentryimpl.cpp \ + datebookdayheaderimpl.cpp \ + datebooksettings.cpp \ + datebookweek.cpp \ + datebookweekheaderimpl.cpp \ + repeatentry.cpp + +INTERFACES = dateentry.ui \ + datebookdayheader.ui \ + datebooksettingsbase.ui \ + datebookweekheader.ui \ + repeatentrybase.ui + +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe + +TARGET = datebook + +TRANSLATIONS = ../i18n/de/datebook.ts diff --git a/core/pim/datebook/datebookday.cpp b/core/pim/datebook/datebookday.cpp new file mode 100644 index 0000000..d5daab2 --- a/dev/null +++ b/core/pim/datebook/datebookday.cpp @@ -0,0 +1,553 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "datebookday.h" +#include "datebookdayheaderimpl.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +DateBookDayView::DateBookDayView( bool whichClock, QWidget *parent, + const char *name ) + : QTable( 24, 1, parent, name ), + ampm( whichClock ) +{ + enableClipper(TRUE); + setTopMargin( 0 ); + horizontalHeader()->hide(); + setLeftMargin(38); + setColumnStretchable( 0, TRUE ); + setHScrollBarMode( QScrollView::AlwaysOff ); + verticalHeader()->setPalette(white); + verticalHeader()->setResizeEnabled(FALSE); + setSelectionMode( Single ); + + // get rid of being able to edit things... + QTableItem *tmp; + int row; + for ( row = 0; row < numRows(); row++ ) { + tmp = new QTableItem( this, QTableItem::Never, QString::null); + setItem( row, 0, tmp ); + } + initHeader(); + QObject::connect( qApp, SIGNAL(clockChanged(bool)), + this, SLOT(slotChangeClock(bool)) ); +} + +void DateBookDayView::initHeader() +{ + QString strTmp; + for ( int i = 0; i < 24; ++i ) { + if ( ampm ) { + if ( i == 0 ) + strTmp = QString::number(12) + ":00"; + else if ( i == 12 ) + strTmp = QString::number(12) + tr(":00p"); + else if ( i > 12 ) + strTmp = QString::number( i - 12 ) + tr(":00p"); + else + strTmp = QString::number(i) + ":00"; + } else { + if ( i < 10 ) + strTmp = "0" + QString::number(i) + ":00"; + else + strTmp = QString::number(i) + ":00"; + } + strTmp = strTmp.rightJustify( 6, ' ' ); + verticalHeader()->setLabel( i, strTmp ); + setRowStretchable( i, FALSE ); + } +} + +void DateBookDayView::slotChangeClock( bool newClock ) +{ + ampm = newClock; + initHeader(); +} + +bool DateBookDayView::whichClock() const +{ + return ampm; +} + +void DateBookDayView::moveUp() +{ + scrollBy(0, -20); +} + +void DateBookDayView::moveDown() +{ + scrollBy(0, 20); +} + +void DateBookDayView::paintCell( QPainter *p, int, int, const QRect &cr, bool ) +{ + int w = cr.width(); + int h = cr.height(); + p->fillRect( 0, 0, w, h, colorGroup().brush( QColorGroup::Base ) ); + if ( showGrid() ) { + // Draw our lines + int x2 = w - 1; + int y2 = h - 1; + QPen pen( p->pen() ); + p->setPen( colorGroup().mid() ); + p->drawLine( x2, 0, x2, y2 ); + p->drawLine( 0, y2, x2, y2 ); + p->setPen( pen ); + } +} + +void DateBookDayView::paintFocus( QPainter *, const QRect & ) +{ +} + + +void DateBookDayView::resizeEvent( QResizeEvent *e ) +{ + QTable::resizeEvent( e ); + columnWidthChanged( 0 ); + emit sigColWidthChanged(); +} + +void DateBookDayView::keyPressEvent( QKeyEvent *e ) +{ + QString txt = e->text(); + if ( !txt.isNull() && txt[0] > ' ' && e->key() < 0x1000 ) { + // we this is some sort of thing we know about... + e->accept(); + emit sigCapturedKey( txt ); + } else { + // I don't know what this key is, do you? + e->ignore(); + } +} + + +//=========================================================================== + +DateBookDay::DateBookDay( bool ampm, bool startOnMonday, + DateBookDB *newDb, QWidget *parent, + const char *name ) + : QVBox( parent, name ), + currDate( QDate::currentDate() ), + db( newDb ), + startTime( 0 ) +{ + widgetList.setAutoDelete( true ); + header = new DateBookDayHeader( startOnMonday, this, "day header" ); + header->setDate( currDate.year(), currDate.month(), currDate.day() ); + view = new DateBookDayView( ampm, this, "day view" ); + connect( header, SIGNAL( dateChanged( int, int, int ) ), + this, SLOT( dateChanged( int, int, int ) ) ); + connect( view, SIGNAL( sigColWidthChanged() ), + this, SLOT( slotColWidthChanged() ) ); + connect( qApp, SIGNAL(weekChanged(bool)), + this, SLOT(slotWeekChanged(bool)) ); + connect( view, SIGNAL(sigCapturedKey(const QString &)), + this, SIGNAL(sigNewEvent(const QString&)) ); +} + +void DateBookDay::selectedDates( QDateTime &start, QDateTime &end ) +{ + start.setDate( currDate ); + end.setDate( currDate ); + + int sh=99,eh=-1; + + int n = dayView()->numSelections(); + + for (int i=0; iselection( i ); + sh = QMIN(sh,sel.topRow()); + eh = QMAX(sh,sel.bottomRow()+1); + } + if (sh > 23 || eh < 1) { + sh=8; + eh=9; + } + + start.setTime( QTime( sh, 0, 0 ) ); + end.setTime( QTime( eh, 0, 0 ) ); +} + +void DateBookDay::setDate( int y, int m, int d ) +{ + header->setDate( y, m, d ); +} + +void DateBookDay::setDate( QDate d) +{ + header->setDate( d.year(), d.month(), d.day() ); +} + +void DateBookDay::dateChanged( int y, int m, int d ) +{ + QDate date( y, m, d ); + if ( currDate == date ) + return; + currDate.setYMD( y, m, d ); + relayoutPage(); + dayView()->clearSelection(); + QTableSelection ts; + ts.init( startTime, 0 ); + ts.expandTo( startTime, 0 ); + dayView()->addSelection( ts ); +} + +void DateBookDay::redraw() +{ + if ( isUpdatesEnabled() ) + relayoutPage(); +} + +void DateBookDay::getEvents() +{ + widgetList.clear(); + + QValueList eventList = db->getEffectiveEvents( currDate, + currDate ); + QValueListIterator it; + for ( it = eventList.begin(); it != eventList.end(); ++it ) { + DateBookDayWidget* w = new DateBookDayWidget( *it, this ); + connect( w, SIGNAL( deleteMe( const Event & ) ), + this, SIGNAL( removeEvent( const Event & ) ) ); + connect( w, SIGNAL( editMe( const Event & ) ), + this, SIGNAL( editEvent( const Event & ) ) ); + connect( w, SIGNAL( beamMe( const Event & ) ), + this, SIGNAL( beamEvent( const Event & ) ) ); + widgetList.append( w ); + } +} + +static int place( const DateBookDayWidget *item, bool *used, int maxn ) +{ + int place = 0; + int start = item->event().start().hour(); + QTime e = item->event().end(); + int end = e.hour(); + if ( e.minute() < 5 ) + end--; + if ( end < start ) + end = start; + while ( place < maxn ) { + bool free = TRUE; + int s = start; + while( s <= end ) { + if ( used[10*s+place] ) { + free = FALSE; + break; + } + s++; + } + if ( free ) break; + place++; + } + if ( place == maxn ) { + return -1; + } + while( start <= end ) { + used[10*start+place] = TRUE; + start++; + } + return place; +} + + +void DateBookDay::relayoutPage( bool fromResize ) +{ + setUpdatesEnabled( FALSE ); + if ( !fromResize ) + getEvents(); // no need we already have them! + + int wCount = widgetList.count(); + int wid = view->columnWidth(0)-1; + int n = 1; + + if ( wCount < 20 ) { + for ( int i = 0; i < wCount; ) { + DateBookDayWidget *w = widgetList.at(i); + int x = 0; + int xp = 0; + QRect geom = w->geometry(); + geom.setX( x ); + geom.setWidth( wid ); + while ( xp < n && intersects( w, geom ) ) { + x += wid; + xp++; + geom.moveBy( wid, 0 ); + } + if ( xp >= n ) { + n++; + wid = ( view->columnWidth(0)-1 ) / n; + i = 0; + } else { + w->setGeometry( geom ); + i++; + } + } + view->setContentsPos( 0, startTime * view->rowHeight(0) ); + } else { + + + int hours[24]; + memset( hours, 0, 24*sizeof( int ) ); + bool overFlow = FALSE; + for ( int i = 0; i < wCount; i++ ) { + DateBookDayWidget *w = widgetList.at(i); + int start = w->event().start().hour(); + QTime e = w->event().end(); + int end = e.hour(); + if ( e.minute() < 5 ) + end--; + if ( end < start ) + end = start; + while( start <= end ) { + hours[start]++; + if ( hours[start] >= 10 ) + overFlow = TRUE; + ++start; + } + if ( overFlow ) + break; + } + for ( int i = 0; i < 24; i++ ) { + n = QMAX( n, hours[i] ); + } + wid = ( view->columnWidth(0)-1 ) / n; + + bool used[24*10]; + memset( used, FALSE, 24*10*sizeof( bool ) ); + + for ( int i = 0; i < wCount; i++ ) { + DateBookDayWidget *w = widgetList.at(i); + int xp = place( w, used, n ); + if ( xp != -1 ) { + QRect geom = w->geometry(); + geom.setX( xp*wid ); + geom.setWidth( wid ); + w->setGeometry( geom ); + } + } + view->setContentsPos( 0, startTime * view->rowHeight(0) ); + } + setUpdatesEnabled( TRUE ); + return; +} + +DateBookDayWidget *DateBookDay::intersects( const DateBookDayWidget *item, const QRect &geom ) +{ + int i = 0; + DateBookDayWidget *w = widgetList.at(i); + int wCount = widgetList.count(); + while ( i < wCount && w != item ) { + if ( w->geometry().intersects( geom ) ) { + return w; + } + w = widgetList.at(++i); + } + + return 0; +} + + +QDate DateBookDay::date() const +{ + return currDate; +} + +void DateBookDay::setStartViewTime( int startHere ) +{ + startTime = startHere; + dayView()->clearSelection(); + QTableSelection ts; + ts.init( startTime, 0 ); + ts.expandTo( startTime, 0 ); + dayView()->addSelection( ts ); +} + +int DateBookDay::startViewTime() const +{ + return startTime; +} + +void DateBookDay::slotWeekChanged( bool bStartOnMonday ) +{ + header->setStartOfWeek( bStartOnMonday ); + // redraw(); +} + +void DateBookDay::keyPressEvent(QKeyEvent *e) +{ + switch(e->key()) { + case Key_Up: + view->moveUp(); + break; + case Key_Down: + view->moveDown(); + break; + case Key_Left: + setDate(QDate(currDate).addDays(-1)); + break; + case Key_Right: + setDate(QDate(currDate).addDays(1)); + break; + default: + e->ignore(); + } +} + +//=========================================================================== + +DateBookDayWidget::DateBookDayWidget( const EffectiveEvent &e, + DateBookDay *db ) + : QWidget( db->dayView()->viewport() ), ev( e ), dateBook( db ) +{ + bool whichClock = db->dayView()->whichClock(); + + // why would someone use "<"? Oh well, fix it up... + // I wonder what other things may be messed up... + QString strDesc = ev.description(); + int where = strDesc.find( "<" ); + while ( where != -1 ) { + strDesc.remove( where, 1 ); + strDesc.insert( where, "<" ); + where = strDesc.find( "<", where ); + } + + QString strCat; + // ### Fix later... +// QString strCat = ev.category(); +// where = strCat.find( "<" ); +// while ( where != -1 ) { +// strCat.remove( where, 1 ); +// strCat.insert( where, "<" ); +// where = strCat.find( "<", where ); +// } + + QString strNote = ev.notes(); + where = strNote.find( "<" ); + while ( where != -1 ) { + strNote.remove( where, 1 ); + strNote.insert( where, "<" ); + where = strNote.find( "<", where ); + } + + text = "" + strDesc + "
" + "" + + strCat + "" + + "
" + tr("Start") + ": "; + + + if ( e.startDate() != ev.date() ) { + // multi-day event. Show start date + text += TimeString::longDateString( e.startDate() ); + } else { + // Show start time. + text += TimeString::timeString( ev.start(), whichClock, FALSE ); + } + + text += "
" + tr("End") + ": "; + if ( e.endDate() != ev.date() ) { + // multi-day event. Show end date + text += TimeString::longDateString( e.endDate() ); + } else { + // Show end time. + text += TimeString::timeString( ev.end(), whichClock, FALSE ); + } + text += "

" + strNote; + setBackgroundMode( PaletteBase ); + + QTime s = ev.start(); + QTime e = ev.end(); + int y = s.hour()*60+s.minute(); + int h = e.hour()*60+e.minute()-y; + int rh = dateBook->dayView()->rowHeight(0); + y = y*rh/60; + h = h*rh/60; + if ( h < 3 ) + h = 3; + geom.setY( y ); + geom.setHeight( h ); +} + +DateBookDayWidget::~DateBookDayWidget() +{ +} + +void DateBookDayWidget::paintEvent( QPaintEvent *e ) +{ + QPainter p( this ); + p.setPen( QColor(100, 100, 100) ); + p.setBrush( QColor( 255, 240, 230 ) ); // based on priority? + p.drawRect(rect()); + + int y = 0; + int d = 0; + + if ( ev.event().hasAlarm() ) { + p.drawPixmap( width() - 16, 0, Resource::loadPixmap( "bell" ) ); + y = 20; + d = 20; + } + + if ( ev.event().hasRepeat() ) { + p.drawPixmap( width() - 16, y, Resource::loadPixmap( "repeat" ) ); + d = 20; + } + + QSimpleRichText rt( text, font() ); + rt.setWidth( geom.width() - d - 6 ); + rt.draw( &p, 3, 0, e->region(), colorGroup() ); +} + +void DateBookDayWidget::mousePressEvent( QMouseEvent *e ) +{ + QPopupMenu m; + m.insertItem( tr( "Edit" ), 1 ); + m.insertItem( tr( "Delete" ), 2 ); + m.insertItem( tr( "Beam" ), 3 ); + int r = m.exec( e->globalPos() ); + if ( r == 1 ) { + emit editMe( ev.event() ); + } else if ( r == 2 ) { + emit deleteMe( ev.event() ); + } else if ( r == 3 ) { + emit beamMe( ev.event() ); + } +} + +void DateBookDayWidget::setGeometry( const QRect &r ) +{ + geom = r; + setFixedSize( r.width()+1, r.height()+1 ); + dateBook->dayView()->moveChild( this, r.x(), r.y()-1 ); + show(); +} diff --git a/core/pim/datebook/datebookday.h b/core/pim/datebook/datebookday.h new file mode 100644 index 0000000..531fded --- a/dev/null +++ b/core/pim/datebook/datebookday.h @@ -0,0 +1,138 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef DATEBOOKDAY_H +#define DATEBOOKDAY_H + +#include + +#include +#include +#include +#include + +class DateBookDayHeader; +class DateBookDB; +class QDateTime; +class QMouseEvent; +class QPaintEvent; +class QResizeEvent; + +class DateBookDayView : public QTable +{ + Q_OBJECT +public: + DateBookDayView( bool hourClock, QWidget *parent, const char *name ); + bool whichClock() const; + +public slots: + void moveUp(); + void moveDown(); + +signals: + void sigColWidthChanged(); + void sigCapturedKey( const QString &txt ); +protected slots: + void slotChangeClock( bool ); +protected: + virtual void paintCell( QPainter *p, int row, int col, const QRect &cr, bool selected ); + virtual void paintFocus( QPainter *p, const QRect &cr ); + virtual void resizeEvent( QResizeEvent *e ); + void keyPressEvent( QKeyEvent *e ); + void initHeader(); +private: + bool ampm; +}; + +class DateBookDay; +class DateBookDayWidget : public QWidget +{ + Q_OBJECT + +public: + DateBookDayWidget( const EffectiveEvent &e, DateBookDay *db ); + ~DateBookDayWidget(); + + const QRect &geometry() { return geom; } + void setGeometry( const QRect &r ); + + const EffectiveEvent &event() const { return ev; } + +signals: + void deleteMe( const Event &e ); + void editMe( const Event &e ); + void beamMe( const Event &e ); + +protected: + void paintEvent( QPaintEvent *e ); + void mousePressEvent( QMouseEvent *e ); + +private: + const EffectiveEvent ev; + DateBookDay *dateBook; + QString text; + QRect geom; +}; + +class DateBookDay : public QVBox +{ + Q_OBJECT + +public: + DateBookDay( bool ampm, bool startOnMonday, DateBookDB *newDb, + QWidget *parent, const char *name ); + void selectedDates( QDateTime &start, QDateTime &end ); + QDate date() const; + DateBookDayView *dayView() const { return view; } + void setStartViewTime( int startHere ); + int startViewTime() const; + +public slots: + void setDate( int y, int m, int d ); + void setDate( QDate ); + void redraw(); + void slotWeekChanged( bool bStartOnMonday ); + +signals: + void removeEvent( const Event& ); + void editEvent( const Event& ); + void beamEvent( const Event& ); + void newEvent(); + void sigNewEvent( const QString & ); + +protected slots: + void keyPressEvent(QKeyEvent *); + +private slots: + void dateChanged( int y, int m, int d ); + void slotColWidthChanged() { relayoutPage(); }; + +private: + void getEvents(); + void relayoutPage( bool fromResize = false ); + DateBookDayWidget *intersects( const DateBookDayWidget *item, const QRect &geom ); + QDate currDate; + DateBookDayView *view; + DateBookDayHeader *header; + DateBookDB *db; + QList widgetList; + int startTime; +}; + +#endif diff --git a/core/pim/datebook/datebookdayheader.ui b/core/pim/datebook/datebookdayheader.ui new file mode 100644 index 0000000..8bc284f --- a/dev/null +++ b/core/pim/datebook/datebookdayheader.ui @@ -0,0 +1,424 @@ + +DateBookDayHeaderBase +/********************************************************************** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +** $Id$ +** +**********************************************************************/ + + QWidget + + name + DateBookDayHeaderBase + + + geometry + + 0 + 0 + 249 + 26 + + + + caption + Form1 + + + layoutMargin + + + layoutSpacing + + + + margin + 0 + + + spacing + 0 + + + QToolButton + + name + back + + + text + + + + pixmap + image0 + + + toggleButton + false + + + autoRepeat + true + + + autoRaise + true + + + toggleButton + false + + + toolTip + + + + + QToolButton + + name + date + + + sizePolicy + + 7 + 1 + + + + font + + 1 + + + + text + + + + pixmap + + + + autoRepeat + false + + + autoRaise + false + + + + QButtonGroup + + name + grpDays + + + frameShape + NoFrame + + + frameShadow + Plain + + + title + + + + exclusive + true + + + layoutMargin + + + layoutSpacing + + + + margin + 0 + + + spacing + 1 + + + QToolButton + + name + cmdDay1 + + + text + M + + + toggleButton + true + + + autoRaise + true + + + toggleButton + true + + + toolTip + + + + + QToolButton + + name + cmdDay2 + + + text + T + + + toggleButton + true + + + autoRaise + true + + + toggleButton + true + + + toolTip + + + + + QToolButton + + name + cmdDay3 + + + text + W + + + toggleButton + true + + + autoRaise + true + + + toggleButton + true + + + toolTip + + + + + QToolButton + + name + cmdDay4 + + + text + T + + + pixmap + + + + toggleButton + true + + + autoRepeat + false + + + autoRaise + true + + + toggleButton + true + + + toolTip + + + + + QToolButton + + name + cmdDay5 + + + text + F + + + toggleButton + true + + + autoRaise + true + + + toggleButton + true + + + toolTip + + + + + QToolButton + + name + cmdDay6 + + + text + S + + + toggleButton + true + + + autoRaise + true + + + toggleButton + true + + + toolTip + + + + + QToolButton + + name + cmdDay7 + + + text + S + + + toggleButton + true + + + autoRaise + true + + + toggleButton + true + + + toolTip + + + + + + + QToolButton + + name + forward + + + text + + + + pixmap + image1 + + + autoRepeat + true + + + autoRaise + true + + + + + + + image0 + 789c6dcfcd4e843010c0f13b4fd1d01b31bb6cb325211b1f41e3d1c4789876a60bcbd7aeae07637c773b6d5985d870e0f7ef50605b88e7a707516cb3f72b5c5b2b6c036fa2c08f61f87c79bdffcaf2dd5ef0558b5d7e97e51b61c5e33412df4b7f2fcbb09896a94ab557817063cd744cad74a915734aac35308740d018d9332d5ab0c8ec1229f2c2448d156a661b489ee1ab4e4cf2a08a790e24020abb0dd355442eec8e914e45526215790c749e8e89891069125de466b1fe14295705ccaa5863e2d05cc01894925b2a7e8217dd8a631eb169fd509af10fd1a9ebfbdf32008d9d0c07cd274f70ee162773ba2cdfee935c977ffe6b2edf87ec07796f81cd + + + image1 + 789c7dcfc94ec3301006e07b9ec28a6f114a13cbb1a8108f00e28884387819676993340b07847877329ea8697a60ec83bfdf232f8784bdbfbdb0e4104db39e6bcb6ca54796b8afb6fdfef87cfe89e25cb2650ac1f2f8218a5366d96bdf01aef9b2e65928a4458a0c07b25c29890352e63293e19c53a0968f52230159e8c22981744495133552097554a1f982b4ce6aeb9013d215165c81ec894e109b4070ca85378f2b35f18c04050214b20d04d010762ba457003eecd6442f88f34a45f4817ea147762b35d1acf4c47457d784737d9f18ebee1363614bf852c6f812b6c460f90abb6e93ba694ed7c49fdbaeee2f76b83da71ba772e0db5d9ccf4b07dfdd5e858edd9b2948fff9d796fc3e457f660e8d47 + + + + + forward + clicked() + DateBookDayHeaderBase + goForward() + + + back + clicked() + DateBookDayHeaderBase + goBack() + + + grpDays + clicked(int) + DateBookDayHeaderBase + setDay( int ) + + goBack() + goForward() + setDate( int, int, int ) + setDay( int ) + + diff --git a/core/pim/datebook/datebookdayheaderimpl.cpp b/core/pim/datebook/datebookdayheaderimpl.cpp new file mode 100644 index 0000000..fbcb3d2 --- a/dev/null +++ b/core/pim/datebook/datebookdayheaderimpl.cpp @@ -0,0 +1,181 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "datebookdayheaderimpl.h" + +#include +#include + +#include +#include +#include +#include +#include + +/* + * Constructs a DateBookDayHeader which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +DateBookDayHeader::DateBookDayHeader( bool useMonday, + QWidget* parent, const char* name ) + : DateBookDayHeaderBase( parent, name ), + bUseMonday( useMonday ) +{ + connect(date,SIGNAL(pressed()),this,SLOT(pickDate())); + + setupNames(); + + setBackgroundMode( PaletteButton ); + grpDays->setBackgroundMode( PaletteButton ); +} + +/* + * Destroys the object and frees any allocated resources + */ +DateBookDayHeader::~DateBookDayHeader() +{ + // no need to delete child widgets, Qt does it all for us +} + +void DateBookDayHeader::setStartOfWeek( bool onMonday ) +{ + bUseMonday = onMonday; + setupNames(); + setDate( currDate.year(), currDate.month(), currDate.day() ); +} + +void DateBookDayHeader::setupNames() +{ + if ( bUseMonday ) { + cmdDay1->setText( DateBookDayHeaderBase::tr("Monday").left(1) ); + cmdDay2->setText( DateBookDayHeaderBase::tr("Tuesday").left(1) ); + cmdDay3->setText( DateBookDayHeaderBase::tr("Wednesday").left(1) ); + cmdDay4->setText( DateBookDayHeaderBase::tr("Thursday").left(1) ); + cmdDay5->setText( DateBookDayHeaderBase::tr("Friday").left(1) ); + cmdDay6->setText( DateBookDayHeaderBase::tr("Saturday").left(1) ); + cmdDay7->setText( DateBookDayHeaderBase::tr("Sunday").left(1) ); + } else { + cmdDay1->setText( DateBookDayHeaderBase::tr("Sunday").left(1) ); + cmdDay2->setText( DateBookDayHeaderBase::tr("Monday").left(1) ); + cmdDay3->setText( DateBookDayHeaderBase::tr("Tuesday").left(1) ); + cmdDay4->setText( DateBookDayHeaderBase::tr("Wednesday").left(1) ); + cmdDay5->setText( DateBookDayHeaderBase::tr("Thursday").left(1) ); + cmdDay6->setText( DateBookDayHeaderBase::tr("Friday").left(1) ); + cmdDay7->setText( DateBookDayHeaderBase::tr("Saturday").left(1) ); + } +} + + +void DateBookDayHeader::pickDate() +{ + static QPopupMenu *m1 = 0; + static DateBookMonth *picker = 0; + if ( !m1 ) { + m1 = new QPopupMenu( this ); + picker = new DateBookMonth( m1, 0, TRUE ); + m1->insertItem( picker ); + connect( picker, SIGNAL( dateClicked( int, int, int ) ), + this, SLOT( setDate( int, int, int ) ) ); + connect( m1, SIGNAL( aboutToHide() ), + this, SLOT( gotHide() ) ); + } + picker->setDate( currDate.year(), currDate.month(), currDate.day() ); + m1->popup(mapToGlobal(date->pos()+QPoint(0,date->height()))); + picker->setFocus(); +} + +void DateBookDayHeader::gotHide() +{ + // we have to redo the button... + date->setDown( false ); +} + +/* + * public slot + */ +void DateBookDayHeader::goBack() +{ + currDate = currDate.addDays( -1 ); + setDate( currDate.year(), currDate.month(), currDate.day() ); +} +/* + * public slot + */ +void DateBookDayHeader::goForward() +{ + currDate = currDate.addDays( 1 ); + setDate( currDate.year(), currDate.month(), currDate.day() ); +} + + +/* + * public slot + */ +void DateBookDayHeader::setDate( int y, int m, int d ) +{ + currDate.setYMD( y, m, d ); + date->setText( TimeString::shortDate( currDate ) ); + + int iDayOfWeek = currDate.dayOfWeek(); + // cleverly adjust the day depending on how we start the week + if ( bUseMonday ) + iDayOfWeek--; + else { + if ( iDayOfWeek == 7 ) // Sunday + iDayOfWeek = 0; + } + grpDays->setButton( iDayOfWeek ); + emit dateChanged( y, m, d ); +} + +/* + * public slot + */ +void DateBookDayHeader::setDay( int day ) +{ + int realDay; + int dayOfWeek = currDate.dayOfWeek(); + + // a little adjustment is needed... + if ( bUseMonday ) + realDay = day + 1 ; + else if ( !bUseMonday && day == 0 ) // sunday + realDay = 7; + else + realDay = day; + // special cases first... + if ( realDay == 7 && !bUseMonday ) { + while ( currDate.dayOfWeek() != realDay ) + currDate = currDate.addDays( -1 ); + } else if ( !bUseMonday && dayOfWeek == 7 && dayOfWeek > realDay ) { + while ( currDate.dayOfWeek() != realDay ) + currDate = currDate.addDays( 1 ); + } else if ( dayOfWeek < realDay ) { + while ( currDate.dayOfWeek() < realDay ) + currDate = currDate.addDays( 1 ); + } else if ( dayOfWeek > realDay ) { + while ( currDate.dayOfWeek() > realDay ) + currDate = currDate.addDays( -1 ); + } + // update the date... + setDate( currDate.year(), currDate.month(), currDate.day() ); +} diff --git a/core/pim/datebook/datebookdayheaderimpl.h b/core/pim/datebook/datebookdayheaderimpl.h new file mode 100644 index 0000000..43f3a93 --- a/dev/null +++ b/core/pim/datebook/datebookdayheaderimpl.h @@ -0,0 +1,57 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef DATEBOOKDAYHEADER_H +#define DATEBOOKDAYHEADER_H +#include "datebookdayheader.h" + +#include + +class DateBookDayHeader : public DateBookDayHeaderBase +{ + Q_OBJECT + +public: + DateBookDayHeader( bool bUseMonday, QWidget* parent = 0, + const char* name = 0 ); + ~DateBookDayHeader(); + void setStartOfWeek( bool onMonday ); + +public slots: + void goBack(); + void goForward(); + void setDate( int, int, int ); + void setDay( int ); + void gotHide(); + +signals: + void dateChanged( int y, int m, int d ); + +private slots: + void pickDate(); + + +private: + QDate currDate; + bool bUseMonday; + void setupNames(); + +}; + +#endif // DATEBOOKDAYHEADER_H diff --git a/core/pim/datebook/datebooksettings.cpp b/core/pim/datebook/datebooksettings.cpp new file mode 100644 index 0000000..c5d8ac1 --- a/dev/null +++ b/core/pim/datebook/datebooksettings.cpp @@ -0,0 +1,135 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "datebooksettings.h" + +#include + +#include +#include +#include + +DateBookSettings::DateBookSettings( bool whichClock, QWidget *parent, + const char *name, bool modal, WFlags fl ) + : DateBookSettingsBase( parent, name, modal, fl ), + ampm( whichClock ) +{ + init(); + QObject::connect( qApp, SIGNAL( clockChanged( bool ) ), + this, SLOT( slotChangeClock( bool ) ) ); +} + +DateBookSettings::~DateBookSettings() +{ +} + +void DateBookSettings::setStartTime( int newStartViewTime ) +{ + if ( ampm ) { + if ( newStartViewTime >= 12 ) { + newStartViewTime %= 12; + if ( newStartViewTime == 0 ) + newStartViewTime = 12; + spinStart->setSuffix( tr(":00 PM") ); + } + else if ( newStartViewTime == 0 ) { + newStartViewTime = 12; + spinStart->setSuffix( tr(":00 AM") ); + } + oldtime = newStartViewTime; + } + spinStart->setValue( newStartViewTime ); +} + +int DateBookSettings::startTime() const +{ + int returnMe = spinStart->value(); + if ( ampm ) { + if ( returnMe != 12 && spinStart->suffix().contains(tr("PM"), FALSE) ) + returnMe += 12; + else if (returnMe == 12 && spinStart->suffix().contains(tr("AM"), TRUE)) + returnMe = 0; + } + return returnMe; +} + + +void DateBookSettings::setAlarmPreset( bool bAlarm, int presetTime ) +{ + chkAlarmPreset->setChecked( bAlarm ); + if ( presetTime >=5 ) + spinPreset->setValue( presetTime ); +} + +bool DateBookSettings::alarmPreset() const +{ + return chkAlarmPreset->isChecked(); +} + +int DateBookSettings::presetTime() const +{ + return spinPreset->value(); +} + + +void DateBookSettings::slot12Hour( int i ) +{ + if ( ampm ) { + if ( spinStart->suffix().contains( tr("AM"), FALSE ) ) { + if ( oldtime == 12 && i == 11 || oldtime == 11 && i == 12 ) + spinStart->setSuffix( tr(":00 PM") ); + } else { + if ( oldtime == 12 && i == 11 || oldtime == 11 && i == 12 ) + spinStart->setSuffix( tr(":00 AM") ); + } + oldtime = i; + } +} + +void DateBookSettings::init() +{ + if ( ampm ) { + spinStart->setMinValue( 1 ); + spinStart->setMaxValue( 12 ); + spinStart->setValue( 12 ); + spinStart->setSuffix( tr(":00 AM") ); + oldtime = 12; + } else { + spinStart->setMinValue( 0 ); + spinStart->setMaxValue( 23 ); + spinStart->setSuffix( tr(":00") ); + } +} + +void DateBookSettings::slotChangeClock( bool whichClock ) +{ + int saveMe; + saveMe = spinStart->value(); + if ( ampm && spinStart->suffix().contains( tr("AM"), FALSE ) ) { + if ( saveMe == 12 ) + saveMe = 0; + } else if ( ampm && spinStart->suffix().contains( tr("PM"), FALSE ) ) { + if ( saveMe != 12 ) + saveMe += 12; + } + ampm = whichClock; + init(); + setStartTime( saveMe ); +} diff --git a/core/pim/datebook/datebooksettings.h b/core/pim/datebook/datebooksettings.h new file mode 100644 index 0000000..ee9f39c --- a/dev/null +++ b/core/pim/datebook/datebooksettings.h @@ -0,0 +1,48 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef DATEBOOKSETTINGS_H +#define DATEBOOKSETTINGS_H +#include "datebooksettingsbase.h" + +class DateBookSettings : public DateBookSettingsBase +{ +public: + DateBookSettings( bool whichClock, QWidget *parent = 0, + const char *name = 0, bool modal = TRUE, WFlags = 0 ); + ~DateBookSettings(); + void setStartTime( int newStartViewTime ); + int startTime() const; + void setAlarmPreset( bool bAlarm, int presetTime ); + bool alarmPreset() const; + int presetTime() const; + void setAlarmType( int alarmType ); + int alarmType() const; + +private slots: + void slot12Hour( int ); + void slotChangeClock( bool ); + +private: + void init(); + bool ampm; + int oldtime; +}; +#endif diff --git a/core/pim/datebook/datebooksettingsbase.ui b/core/pim/datebook/datebooksettingsbase.ui new file mode 100644 index 0000000..0f40773 --- a/dev/null +++ b/core/pim/datebook/datebooksettingsbase.ui @@ -0,0 +1,232 @@ + +DateBookSettingsBase +********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +** $Id$ +** +********************************************************************** + + QDialog + + name + DateBookSettingsBase + + + geometry + + 0 + 0 + 232 + 290 + + + + caption + Preferences + + + layoutMargin + + + layoutSpacing + + + + margin + 5 + + + spacing + 1 + + + QGroupBox + + name + fraStart + + + frameShape + Box + + + frameShadow + Sunken + + + title + Start viewing events + + + + margin + 11 + + + spacing + 6 + + + QLayoutWidget + + name + Layout1 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + lblStartTime + + + text + Start Time: + + + + QSpinBox + + name + spinStart + + + suffix + :00 + + + wrapping + true + + + maxValue + 23 + + + + + + + + QGroupBox + + name + fraAlarm + + + title + Alarm Settings + + + + margin + 11 + + + spacing + 6 + + + QLayoutWidget + + name + Layout6 + + + + margin + 0 + + + spacing + 6 + + + QCheckBox + + name + chkAlarmPreset + + + text + Alarm Preset + + + + QSpinBox + + name + spinPreset + + + enabled + false + + + suffix + minutes + + + maxValue + 180 + + + minValue + 0 + + + lineStep + 5 + + + value + 5 + + + + + + + + + + + chkAlarmPreset + toggled(bool) + spinPreset + setEnabled(bool) + + + spinStart + valueChanged(int) + DateBookSettingsBase + slot12Hour( int ) + + slotChangeClock( bool ) + slot12Hour( int ) + + diff --git a/core/pim/datebook/datebookweek.cpp b/core/pim/datebook/datebookweek.cpp new file mode 100644 index 0000000..e9fcc39 --- a/dev/null +++ b/core/pim/datebook/datebookweek.cpp @@ -0,0 +1,687 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "datebookweek.h" +#include "datebookweekheaderimpl.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//----------------------------------------------------------------- + + +DateBookWeekItem::DateBookWeekItem( const EffectiveEvent e ) + : ev( e ) +{ + // with the current implementation change the color for all day events + if ( ev.event().type() == Event::AllDay && !ev.event().hasAlarm() ) { + c = Qt::green; + } else { + c = ev.event().hasAlarm() ? Qt::red : Qt::blue; + } +} + +void DateBookWeekItem::setGeometry( int x, int y, int w, int h ) +{ + r.setRect( x, y, w, h ); +} + + +//------------------=--------------------------------------------- + +DateBookWeekView::DateBookWeekView( bool ap, bool startOnMonday, + QWidget *parent, const char *name ) + : QScrollView( parent, name ), ampm( ap ), bOnMonday( startOnMonday ), + showingEvent( false ) +{ + items.setAutoDelete( true ); + + viewport()->setBackgroundMode( PaletteBase ); + + header = new QHeader( this ); + header->addLabel( "" ); + + header->setMovingEnabled( false ); + header->setResizeEnabled( false ); + header->setClickEnabled( false, 0 ); + initNames(); + + + connect( header, SIGNAL(clicked(int)), this, SIGNAL(showDay(int)) ); + + QObject::connect(qApp, SIGNAL(clockChanged(bool)), + this, SLOT(slotChangeClock(bool))); + + QFontMetrics fm( font() ); + rowHeight = fm.height()+2; + + resizeContents( width(), 24*rowHeight ); +} + +void DateBookWeekView::initNames() +{ + static bool bFirst = true; + if ( bFirst ) { + if ( bOnMonday ) { + header->addLabel( tr("M", "Monday" ) ); + header->addLabel( tr("T", "Tuesday") ); + header->addLabel( tr("W", "Wednesday" ) ); + header->addLabel( tr("T", "Thursday" ) ); + header->addLabel( tr("F", "Friday" ) ); + header->addLabel( tr("S", "Saturday" ) ); + header->addLabel( tr("S", "Sunday" ) ); + } else { + header->addLabel( tr("S", "Sunday" ) ); + header->addLabel( tr("M", "Monday") ); + header->addLabel( tr("T", "Tuesday") ); + header->addLabel( tr("W", "Wednesday" ) ); + header->addLabel( tr("T", "Thursday" ) ); + header->addLabel( tr("F", "Friday" ) ); + header->addLabel( tr("S", "Saturday" ) ); + } + bFirst = false; + } else { + // we are change things... + if ( bOnMonday ) { + header->setLabel( 1, tr("M", "Monday") ); + header->setLabel( 2, tr("T", "Tuesday") ); + header->setLabel( 3, tr("W", "Wednesday" ) ); + header->setLabel( 4, tr("T", "Thursday" ) ); + header->setLabel( 5, tr("F", "Friday" ) ); + header->setLabel( 6, tr("S", "Saturday" ) ); + header->setLabel( 7, tr("S", "Sunday" ) ); + } else { + header->setLabel( 1, tr("S", "Sunday" ) ); + header->setLabel( 2, tr("M", "Monday") ); + header->setLabel( 3, tr("T", "Tuesday") ); + header->setLabel( 4, tr("W", "Wednesday" ) ); + header->setLabel( 5, tr("T", "Thursday" ) ); + header->setLabel( 6, tr("F", "Friday" ) ); + header->setLabel( 7, tr("S", "Saturday" ) ); + } + } +} + + + +void DateBookWeekView::showEvents( QValueList &ev ) +{ + items.clear(); + QValueListIterator it; + for ( it = ev.begin(); it != ev.end(); ++it ) { + DateBookWeekItem *i = new DateBookWeekItem( *it ); + positionItem( i ); + items.append( i ); + } + viewport()->update(); +} + +void DateBookWeekView::moveToHour( int h ) +{ + int offset = h*rowHeight; + setContentsPos( 0, offset ); +} + +void DateBookWeekView::keyPressEvent( QKeyEvent *e ) +{ + e->ignore(); +} + +void DateBookWeekView::slotChangeClock( bool c ) +{ + ampm = c; + viewport()->update(); +} + +static inline int db_round30min( int m ) +{ + if ( m < 15 ) + m = 0; + else if ( m < 45 ) + m = 1; + else + m = 2; + + return m; +} + +void DateBookWeekView::alterDay( int day ) +{ + if ( !bOnMonday ) { + day--; + } + emit showDay( day ); +} + +void DateBookWeekView::positionItem( DateBookWeekItem *i ) +{ + const int Width = 8; + const EffectiveEvent ev = i->event(); + + // 30 minute intervals + int y = ev.start().hour() * 2; + y += db_round30min( ev.start().minute() ); + if ( y > 47 ) + y = 47; + y = y * rowHeight / 2; + + int h; + if ( ev.event().type() == Event::AllDay ) { + h = 48; + y = 0; + } else { + h = ( ev.end().hour() - ev.start().hour() ) * 2; + h += db_round30min( ev.end().minute() - ev.start().minute() ); + if ( h < 1 ) h = 1; + } + h = h * rowHeight / 2; + + int dow = ev.date().dayOfWeek(); + if ( !bOnMonday ) { + if ( dow == 7 ) + dow = 1; + else + dow++; + } + int x = header->sectionPos( dow ) - 1; + int xlim = header->sectionPos( dow ) + header->sectionSize( dow ); + DateBookWeekItem *isect = 0; + do { + i->setGeometry( x, y, Width, h ); + isect = intersects( i ); + x += Width - 1; + } while ( isect && x < xlim ); +} + +DateBookWeekItem *DateBookWeekView::intersects( const DateBookWeekItem *item ) +{ + QRect geom = item->geometry(); + + // We allow the edges to overlap + geom.moveBy( 1, 1 ); + geom.setSize( geom.size()-QSize(2,2) ); + + QListIterator it(items); + for ( ; it.current(); ++it ) { + DateBookWeekItem *i = it.current(); + if ( i != item ) { + if ( i->geometry().intersects( geom ) ) { + return i; + } + } + } + + return 0; +} + +void DateBookWeekView::contentsMousePressEvent( QMouseEvent *e ) +{ + QListIterator it(items); + for ( ; it.current(); ++it ) { + DateBookWeekItem *i = it.current(); + if ( i->geometry().contains( e->pos() ) ) { + showingEvent = true; + emit signalShowEvent( i->event() ); + break; + } + } +} + +void DateBookWeekView::contentsMouseReleaseEvent( QMouseEvent *e ) +{ + if ( showingEvent ) { + showingEvent = false; + emit signalHideEvent(); + } else { + int d = header->sectionAt( e->pos().x() ); + if ( d > 0 ) { +// if ( !bOnMonday ) +// d--; + emit showDay( d ); + } + } +} + +void DateBookWeekView::drawContents( QPainter *p, int cx, int cy, int cw, int ch ) +{ + QRect ur( cx, cy, cw, ch ); + p->setPen( lightGray ); + for ( int i = 1; i <= 7; i++ ) + p->drawLine( header->sectionPos(i)-2, cy, header->sectionPos(i)-2, cy+ch ); + + p->setPen( black ); + for ( int t = 0; t < 24; t++ ) { + int y = t*rowHeight; + if ( QRect( 1, y, 20, rowHeight ).intersects( ur ) ) { + QString s; + if ( ampm ) { + if ( t == 0 ) + s = QString::number( 12 ); + else if ( t == 12 ) + s = QString::number(12) + tr( "p" ); + else if ( t > 12 ) { + if ( t - 12 < 10 ) + s = " "; + else + s = ""; + s += QString::number( t - 12 ) + tr("p"); + } else { + if ( 12 - t < 3 ) + s = ""; + else + s = " "; + s += QString::number( t ); + } + } else { + s = QString::number( t ); + if ( s.length() == 1 ) + s.prepend( "0" ); + } + p->drawText( 1, y+p->fontMetrics().ascent()+1, s ); + } + } + + QListIterator it(items); + for ( ; it.current(); ++it ) { + DateBookWeekItem *i = it.current(); + if ( i->geometry().intersects( ur ) ) { + p->setBrush( i->color() ); + p->drawRect( i->geometry() ); + } + } +} + +void DateBookWeekView::resizeEvent( QResizeEvent *e ) +{ + const int hourWidth = 20; + QScrollView::resizeEvent( e ); + int avail = width()-qApp->style().scrollBarExtent().width()-1; + header->setGeometry( 0, 0, avail, header->sizeHint().height() ); + setMargins( 0, header->height(), 0, 0 ); + header->resizeSection( 0, hourWidth ); + int sw = (avail - hourWidth) / 7; + for ( int i = 1; i < 7; i++ ) + header->resizeSection( i, sw ); + header->resizeSection( 7, avail - hourWidth - sw*6 ); +} + +void DateBookWeekView::setStartOfWeek( bool bStartOnMonday ) +{ + bOnMonday = bStartOnMonday; + initNames(); +} + +//------------------------------------------------------------------- + +DateBookWeek::DateBookWeek( bool ap, bool startOnMonday, DateBookDB *newDB, + QWidget *parent, const char *name ) + : QWidget( parent, name ), + db( newDB ), + startTime( 0 ), + ampm( ap ), + bStartOnMonday( startOnMonday ) +{ + setFocusPolicy(StrongFocus); + QVBoxLayout *vb = new QVBoxLayout( this ); + header = new DateBookWeekHeader( bStartOnMonday, this ); + view = new DateBookWeekView( ampm, startOnMonday, this ); + vb->addWidget( header ); + vb->addWidget( view ); + + lblDesc = new QLabel( this, "event label" ); + lblDesc->setFrameStyle( QFrame::Plain | QFrame::Box ); + lblDesc->setBackgroundColor( yellow ); + lblDesc->hide(); + + tHide = new QTimer( this ); + + connect( view, SIGNAL( showDay( int ) ), + this, SLOT( showDay( int ) ) ); + connect( view, SIGNAL(signalShowEvent(const EffectiveEvent&)), + this, SLOT(slotShowEvent(const EffectiveEvent&)) ); + connect( view, SIGNAL(signalHideEvent()), + this, SLOT(slotHideEvent()) ); + connect( header, SIGNAL( dateChanged( int, int ) ), + this, SLOT( dateChanged( int, int ) ) ); + connect( tHide, SIGNAL( timeout() ), + lblDesc, SLOT( hide() ) ); + connect( header->spinYear, SIGNAL(valueChanged(int)), + this, SLOT(slotYearChanged(int)) ); + connect( qApp, SIGNAL(weekChanged(bool)), + this, SLOT(slotWeekChanged(bool)) ); + connect( qApp, SIGNAL(clockChanged(bool)), + this, SLOT(slotClockChanged(bool))); + setDate(QDate::currentDate()); + +} + +void DateBookWeek::keyPressEvent(QKeyEvent *e) +{ + switch(e->key()) { + case Key_Up: + view->scrollBy(0, -20); + break; + case Key_Down: + view->scrollBy(0, 20); + break; + case Key_Left: + setDate(date().addDays(-7)); + break; + case Key_Right: + setDate(date().addDays(7)); + break; + default: + e->ignore(); + } +} + +void DateBookWeek::showDay( int day ) +{ + QDate d; + d = dateFromWeek( _week, year, bStartOnMonday ); + day--; + d = d.addDays( day ); + emit showDate( d.year(), d.month(), d.day() ); +} + +void DateBookWeek::setDate( int y, int m, int d ) +{ + QDate date; + date.setYMD( y, m, d ); + setDate(QDate(y, m, d)); +} + +void DateBookWeek::setDate(QDate date) +{ + dow = date.dayOfWeek(); + int w, y; + calcWeek( date, w, y, bStartOnMonday ); + header->setDate( y, w ); +} + +void DateBookWeek::dateChanged( int y, int w ) +{ + year = y; + _week = w; + getEvents(); +} + +QDate DateBookWeek::date() const +{ + QDate d; + d = dateFromWeek( _week - 1, year, bStartOnMonday ); + if ( bStartOnMonday ) + d = d.addDays( 7 + dow - 1 ); + else { + if ( dow == 7 ) + d = d.addDays( dow ); + else + d = d.addDays( 7 + dow ); + } + return d; +} + +void DateBookWeek::getEvents() +{ + QDate startWeek = weekDate(); + + QDate endWeek = startWeek.addDays( 6 ); + QValueList eventList = db->getEffectiveEvents(startWeek, + endWeek); + view->showEvents( eventList ); + view->moveToHour( startTime ); +} + +void DateBookWeek::slotShowEvent( const EffectiveEvent &ev ) +{ + if ( tHide->isActive() ) + tHide->stop(); + + // why would someone use "<"? Oh well, fix it up... + // I wonder what other things may be messed up... + QString strDesc = ev.description(); + int where = strDesc.find( "<" ); + while ( where != -1 ) { + strDesc.remove( where, 1 ); + strDesc.insert( where, "<" ); + where = strDesc.find( "<", where ); + } + + QString strCat; + // ### FIX later... +// QString strCat = ev.category(); +// where = strCat.find( "<" ); +// while ( where != -1 ) { +// strCat.remove( where, 1 ); +// strCat.insert( where, "<" ); +// where = strCat.find( "<", where ); +// } + + QString strNote = ev.notes(); + where = strNote.find( "<" ); + while ( where != -1 ) { + strNote.remove( where, 1 ); + strNote.insert( where, "<" ); + where = strNote.find( "<", where ); + } + + QString str = "" + strDesc + "
" + "" + + strCat + "" + + "
" + TimeString::longDateString( ev.date() ) + + "
" + QObject::tr("Start") + ": "; + + if ( ev.startDate() != ev.date() ) { + // multi-day event. Show start date + str += TimeString::longDateString( ev.startDate() ); + } else { + // Show start time. + str += TimeString::timeString(ev.start(), ampm, FALSE ); + } + + str += "
" + QObject::tr("End") + ": "; + if ( ev.endDate() != ev.date() ) { + // multi-day event. Show end date + str += TimeString::longDateString( ev.endDate() ); + } else { + // Show end time. + str += TimeString::timeString( ev.end(), ampm, FALSE ); + } + str += "

" + strNote; + + lblDesc->setText( str ); + lblDesc->resize( lblDesc->sizeHint() ); + // move the label so it is "centerd" horizontally... + lblDesc->move( QMAX(0,(width() - lblDesc->width()) / 2), 0 ); + lblDesc->show(); +} + +void DateBookWeek::slotHideEvent() +{ + tHide->start( 2000, true ); +} + +void DateBookWeek::setStartViewTime( int startHere ) +{ + startTime = startHere; + view->moveToHour( startTime ); +} + +int DateBookWeek::startViewTime() const +{ + return startTime; +} + +void DateBookWeek::redraw() +{ + getEvents(); +} + +void DateBookWeek::slotYearChanged( int y ) +{ + int totWeek; + QDate d( y, 12, 31 ); + int throwAway; + calcWeek( d, totWeek, throwAway, bStartOnMonday ); + while ( totWeek == 1 ) { + d = d.addDays( -1 ); + calcWeek( d, totWeek, throwAway, bStartOnMonday ); + } + if ( totWeek != totalWeeks() ) + setTotalWeeks( totWeek ); +} + + +void DateBookWeek::setTotalWeeks( int numWeeks ) +{ + header->spinWeek->setMaxValue( numWeeks ); +} + +int DateBookWeek::totalWeeks() const +{ + return header->spinWeek->maxValue(); +} + +void DateBookWeek::slotWeekChanged( bool onMonday ) +{ + bStartOnMonday = onMonday; + view->setStartOfWeek( bStartOnMonday ); + header->setStartOfWeek( bStartOnMonday ); + redraw(); +} + +void DateBookWeek::slotClockChanged( bool ap ) +{ + ampm = ap; +} + +// return the date at the beginning of the week... +QDate DateBookWeek::weekDate() const +{ + return dateFromWeek( _week, year, bStartOnMonday ); +} + +// this used to only be needed by datebook.cpp, but now we need it inside +// week view since +// we need to be able to figure out our total number of weeks on the fly... +// this is probably the best place to put it.. + +// For Weeks that start on Monday... (EASY!) +// At the moment we will use ISO 8601 method for computing +// the week. Granted, other countries use other methods, +// bet we aren't doing any Locale stuff at the moment. So, +// this should pass. This Algorithim is public domain and +// available at: +// http://personal.ecu.edu/mccartyr/ISOwdALG.txt +// the week number is return, and the year number is returned in year +// for Instance 2001/12/31 is actually the first week in 2002. +// There is a more mathematical definition, but I will implement it when +// we are pass our deadline. + +// For Weeks that start on Sunday... (ahh... home rolled) +// okay, if Jan 1 is on Friday or Saturday, +// it will go to the pervious +// week... + +bool calcWeek( const QDate &d, int &week, int &year, + bool startOnMonday = false ) +{ + int weekNumber; + int yearNumber; + + // remove a pesky warning, (Optimizations on g++) + weekNumber = -1; + int jan1WeekDay = QDate(d.year(), 1, 1).dayOfWeek(); + int dayOfWeek = d.dayOfWeek(); + + if ( !d.isValid() ) + return false; + + if ( startOnMonday ) { + // find the Jan1Weekday; + if ( d.dayOfYear() <= ( 8 - jan1WeekDay) && jan1WeekDay > 4 ) { + yearNumber = d.year() - 1; + if ( jan1WeekDay == 5 || ( jan1WeekDay == 6 && QDate::leapYear(yearNumber) ) ) + weekNumber = 53; + else + weekNumber = 52; + } else + yearNumber = d.year(); + if ( yearNumber == d.year() ) { + int totalDays = 365; + if ( QDate::leapYear(yearNumber) ) + totalDays++; + if ( ((totalDays - d.dayOfYear()) < (4 - dayOfWeek) ) + || (jan1WeekDay == 7) && (totalDays - d.dayOfYear()) < 3) { + yearNumber++; + weekNumber = 1; + } + } + if ( yearNumber == d.year() ) { + int j = d.dayOfYear() + (7 - dayOfWeek) + ( jan1WeekDay - 1 ); + weekNumber = j / 7; + if ( jan1WeekDay > 4 ) + weekNumber--; + } + } else { + // it's better to keep these cases separate... + if ( d.dayOfYear() <= (7 - jan1WeekDay) && jan1WeekDay > 4 + && jan1WeekDay != 7 ) { + yearNumber = d.year() - 1; + if ( jan1WeekDay == 6 + || (jan1WeekDay == 7 && QDate::leapYear(yearNumber) ) ) { + weekNumber = 53; + }else + weekNumber = 52; + } else + yearNumber = d.year(); + if ( yearNumber == d.year() ) { + int totalDays = 365; + if ( QDate::leapYear( yearNumber ) ) + totalDays++; + if ( ((totalDays - d.dayOfYear()) < (4 - dayOfWeek % 7)) ) { + yearNumber++; + weekNumber = 1; + } + } + if ( yearNumber == d.year() ) { + int j = d.dayOfYear() + (7 - dayOfWeek % 7) + ( jan1WeekDay - 1 ); + weekNumber = j / 7; + if ( jan1WeekDay > 4 ) { + weekNumber--; + } + } + } + year = yearNumber; + week = weekNumber; + return true; +} + diff --git a/core/pim/datebook/datebookweek.h b/core/pim/datebook/datebookweek.h new file mode 100644 index 0000000..6e675f1 --- a/dev/null +++ b/core/pim/datebook/datebookweek.h @@ -0,0 +1,152 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef DATEBOOKWEEK +#define DATEBOOKWEEK + +#include + +#include +#include +#include +#include + +class DateBookDB; +class DateBookWeekHeader; +class QDate; +class QLabel; +class QResizeEvent; +class QSpinBox; +class QTimer; +class QHeader; + +class DateBookWeekItem +{ +public: + DateBookWeekItem( const EffectiveEvent e ); + + void setGeometry( int x, int y, int w, int h ); + QRect geometry() const { return r; } + + const QColor &color() const { return c; } + const EffectiveEvent event() const { return ev; } + +private: + const EffectiveEvent ev; + QRect r; + QColor c; +}; + +class DateBookWeekView : public QScrollView +{ + Q_OBJECT +public: + DateBookWeekView( bool ampm, bool weekOnMonday, QWidget *parent = 0, + const char *name = 0 ); + + bool whichClock() const; + void showEvents( QValueList &ev ); + void moveToHour( int h ); + void setStartOfWeek( bool bOnMonday ); + +signals: + void showDay( int d ); + void signalShowEvent( const EffectiveEvent & ); + void signalHideEvent(); + +protected slots: + void keyPressEvent(QKeyEvent *); + +private slots: + void slotChangeClock( bool ); + void alterDay( int ); + +private: + void positionItem( DateBookWeekItem *i ); + DateBookWeekItem *intersects( const DateBookWeekItem * ); + void drawContents( QPainter *p, int cx, int cy, int cw, int ch ); + void contentsMousePressEvent( QMouseEvent * ); + void contentsMouseReleaseEvent( QMouseEvent * ); + void resizeEvent( QResizeEvent * ); + void initNames(); + +private: + bool ampm; + bool bOnMonday; + QHeader *header; + QList items; + int rowHeight; + bool showingEvent; +}; + +class DateBookWeek : public QWidget +{ + Q_OBJECT + +public: + DateBookWeek( bool ampm, bool weekOnMonday, DateBookDB *newDB, + QWidget *parent = 0, const char *name = 0 ); + void setDate( int y, int m, int d ); + void setDate( QDate d ); + QDate date() const; + DateBookWeekView *weekView() const { return view; } + void setStartViewTime( int startHere ); + int startViewTime() const; + int week() const { return _week; }; + void setTotalWeeks( int totalWeeks ); + int totalWeeks() const; + QDate weekDate() const; + +public slots: + void redraw(); + void slotWeekChanged( bool bStartOnMonday ); + void slotClockChanged( bool a ); + +signals: + void showDate( int y, int m, int d ); + +protected slots: + void keyPressEvent(QKeyEvent *); + +private slots: + void showDay( int day ); + void dateChanged( int y, int w ); + void slotShowEvent( const EffectiveEvent & ); + void slotHideEvent(); + void slotYearChanged( int ); + +private: + void getEvents(); + int year; + int _week; + int dow; + DateBookWeekHeader *header; + DateBookWeekView *view; + DateBookDB *db; + QLabel *lblDesc; + QTimer *tHide; + int startTime; + bool ampm; + bool bStartOnMonday; +}; + + +bool calcWeek( const QDate &d, int &week, int &year, + bool startOnMonday = false ); +#endif diff --git a/core/pim/datebook/datebookweekheader.ui b/core/pim/datebook/datebookweekheader.ui new file mode 100644 index 0000000..dd6a5b1 --- a/dev/null +++ b/core/pim/datebook/datebookweekheader.ui @@ -0,0 +1,167 @@ + +DateBookWeekHeaderBase +********************************************************************* +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +********************************************************************* + + QWidget + + name + DateBookWeekHeaderBase + + + geometry + + 0 + 0 + 281 + 30 + + + + caption + Form1 + + + layoutMargin + + + layoutSpacing + + + + margin + 0 + + + spacing + 6 + + + QSpinBox + + name + spinYear + + + sizePolicy + + 0 + 0 + + + + prefix + Y: + + + maxValue + 2037 + + + minValue + 1970 + + + value + 2002 + + + + QSpinBox + + name + spinWeek + + + sizePolicy + + 0 + 0 + + + + prefix + W: + + + maxValue + 52 + + + minValue + 1 + + + value + 1 + + + + QLabel + + name + labelDate + + + sizePolicy + + 3 + 1 + + + + font + + 1 + + + + text + 00. Jan-00. Jan + + + alignment + AlignCenter + + + hAlign + + + + + + + spinYear + valueChanged(int) + DateBookWeekHeaderBase + yearChanged( int ) + + + spinWeek + valueChanged(int) + DateBookWeekHeaderBase + weekChanged( int ) + + yearChanged( int ) + nextWeek() + prevWeek() + weekChanged( int ) + + diff --git a/core/pim/datebook/datebookweekheaderimpl.cpp b/core/pim/datebook/datebookweekheaderimpl.cpp new file mode 100644 index 0000000..e7c7208 --- a/dev/null +++ b/core/pim/datebook/datebookweekheaderimpl.cpp @@ -0,0 +1,126 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "datebookweekheaderimpl.h" +#include +#include +#include + +/* + * Constructs a DateBookWeekHeader which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + */ +DateBookWeekHeader::DateBookWeekHeader( bool startOnMonday, QWidget* parent, + const char* name, WFlags fl ) + : DateBookWeekHeaderBase( parent, name, fl ), + bStartOnMonday( startOnMonday ) +{ + setBackgroundMode( PaletteButton ); + labelDate->setBackgroundMode( PaletteButton ); +} + +/* + * Destroys the object and frees any allocated resources + */ +DateBookWeekHeader::~DateBookWeekHeader() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * public slot + */ +void DateBookWeekHeader::yearChanged( int y ) +{ + setDate( y, week ); +} +/* + * public slot + */ +void DateBookWeekHeader::nextWeek() +{ + if ( week < 52 ) + week++; + setDate( year, week ); +} +/* + * public slot + */ +void DateBookWeekHeader::prevWeek() +{ + if ( week > 1 ) + week--; + setDate( year, week ); +} +/* + * public slot + */ +void DateBookWeekHeader::weekChanged( int w ) +{ + setDate( year, w ); +} + +void DateBookWeekHeader::setDate( int y, int w ) +{ + year = y; + week = w; + spinYear->setValue( y ); + spinWeek->setValue( w ); + + QDate d = dateFromWeek( week, year, bStartOnMonday ); + + QString s = QString::number( d.day() ) + ". " + d.monthName( d.month() ) + + "-"; + d = d.addDays( 6 ); + s += QString::number( d.day() ) + ". " + d.monthName( d.month() ); + labelDate->setText( s ); + + emit dateChanged( y, w ); +} + +void DateBookWeekHeader::setStartOfWeek( bool onMonday ) +{ + bStartOnMonday = onMonday; + setDate( year, week ); +} + +// dateFromWeek +// compute the date from the week in the year + +QDate dateFromWeek( int week, int year, bool startOnMonday ) +{ + QDate d; + d.setYMD( year, 1, 1 ); + int dayOfWeek = d.dayOfWeek(); + if ( startOnMonday ) { + if ( dayOfWeek <= 4 ) { + d = d.addDays( ( week - 1 ) * 7 - dayOfWeek + 1 ); + } else { + d = d.addDays( (week) * 7 - dayOfWeek + 1 ); + } + } else { + if ( dayOfWeek <= 4 || dayOfWeek == 7) { + d = d.addDays( ( week - 1 ) * 7 - dayOfWeek % 7 ); + } else { + d = d.addDays( ( week ) * 7 - dayOfWeek % 7 ); + } + } + return d; +} + diff --git a/core/pim/datebook/datebookweekheaderimpl.h b/core/pim/datebook/datebookweekheaderimpl.h new file mode 100644 index 0000000..2abef46 --- a/dev/null +++ b/core/pim/datebook/datebookweekheaderimpl.h @@ -0,0 +1,62 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef DATEBOOKDAYHEADER_H +#define DATEBOOKDAYHEADER_H +#include +#include "datebookweekheader.h" + + +class DateBookWeekHeader : public DateBookWeekHeaderBase +{ + Q_OBJECT + +public: + DateBookWeekHeader( bool startOnMonday, QWidget* parent = 0, + const char* name = 0, WFlags fl = 0 ); + ~DateBookWeekHeader(); + + void setDate( int y, int w ); + void setStartOfWeek( bool onMonday ); + +signals: + void dateChanged( int y, int w ); + +public slots: + void yearChanged( int ); + void nextWeek(); + void prevWeek(); + void weekChanged( int ); + +protected slots: + void keyPressEvent(QKeyEvent *e) + { + e->ignore(); + } + +private: + int year, + week; + bool bStartOnMonday; + +}; + +QDate dateFromWeek( int week, int year, bool startOnMonday ); + +#endif // DATEBOOKDAYHEADER_H diff --git a/core/pim/datebook/dateentry.ui b/core/pim/datebook/dateentry.ui new file mode 100644 index 0000000..0c363a4 --- a/dev/null +++ b/core/pim/datebook/dateentry.ui @@ -0,0 +1,1095 @@ + +DateEntryBase +********************************************************************* +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +** $Id$ +** +********************************************************************* + + QWidget + + name + DateEntryBase + + + geometry + + 0 + 0 + 242 + 339 + + + + caption + New Event + + + layoutMargin + + + layoutSpacing + + + + margin + 0 + + + spacing + 0 + + + QLabel + + name + TextLabel2 + + + frameShape + MShape + + + frameShadow + MShadow + + + text + Location + + + + QLabel + + name + TextLabel2_2 + + + text + Category + + + buddy + comboPriority + + + + QComboBox + + + text + (None) + + + + + text + Meeting + + + + + text + Lunch + + + + + text + Dinner + + + + + text + Travel + + + + name + comboDescription + + + sizePolicy + + 7 + 0 + + + + editable + true + + + currentItem + 0 + + + duplicatesEnabled + false + + + + QLabel + + name + TextLabel1 + + + text + Description: + + + + QComboBox + + + text + (Unknown) + + + + + text + Office + + + + + text + Home + + + + name + comboLocation + + + sizePolicy + + 7 + 0 + + + + editable + true + + + currentItem + 0 + + + duplicatesEnabled + false + + + + CategorySelect + + name + comboCategory + + + + QLabel + + name + TextLabel3 + + + text + Start + + + + QPushButton + + name + buttonStart + + + text + Jan 02 00 + + + + QComboBox + + + text + 00:00 + + + + + text + 00:30 + + + + + text + 01:00 + + + + + text + 01:30 + + + + + text + 02:00 + + + + + text + 02:30 + + + + + text + 03:00 + + + + + text + 03:30 + + + + + text + 04:00 + + + + + text + 04:30 + + + + + text + 05:00 + + + + + text + 05:30 + + + + + text + 06:00 + + + + + text + 06:30 + + + + + text + 07:00 + + + + + text + 07:30 + + + + + text + 08:00 + + + + + text + 08:30 + + + + + text + 09:00 + + + + + text + 09:30 + + + + + text + 10:00 + + + + + text + 10:30 + + + + + text + 11:00 + + + + + text + 11:30 + + + + + text + 12:00 + + + + + text + 12:30 + + + + + text + 13:00 + + + + + text + 13:30 + + + + + text + 14:00 + + + + + text + 14:30 + + + + + text + 15:00 + + + + + text + 15:30 + + + + + text + 16:00 + + + + + text + 16:30 + + + + + text + 17:00 + + + + + text + 17:30 + + + + + text + 18:00 + + + + + text + 18:30 + + + + + text + 19:00 + + + + + text + 19:30 + + + + + text + 20:00 + + + + + text + 20:30 + + + + + text + 21:00 + + + + + text + 21:30 + + + + + text + 22:00 + + + + + text + 22:30 + + + + + text + 23:00 + + + + + text + 23:30 + + + + name + comboStart + + + editable + true + + + duplicatesEnabled + false + + + + QPushButton + + name + buttonEnd + + + text + Jan 02 00 + + + + QComboBox + + + text + 00:00 + + + + + text + 00:30 + + + + + text + 01:00 + + + + + text + 01:30 + + + + + text + 02:00 + + + + + text + 02:30 + + + + + text + 03:00 + + + + + text + 03:30 + + + + + text + 04:00 + + + + + text + 04:30 + + + + + text + 05:00 + + + + + text + 05:30 + + + + + text + 06:00 + + + + + text + 06:30 + + + + + text + 07:00 + + + + + text + 07:30 + + + + + text + 08:00 + + + + + text + 08:30 + + + + + text + 09:00 + + + + + text + 09:30 + + + + + text + 10:00 + + + + + text + 10:30 + + + + + text + 11:00 + + + + + text + 11:30 + + + + + text + 12:00 + + + + + text + 12:30 + + + + + text + 13:00 + + + + + text + 13:30 + + + + + text + 14:00 + + + + + text + 14:30 + + + + + text + 15:00 + + + + + text + 15:30 + + + + + text + 16:00 + + + + + text + 16:30 + + + + + text + 17:00 + + + + + text + 17:30 + + + + + text + 18:00 + + + + + text + 18:30 + + + + + text + 19:00 + + + + + text + 19:30 + + + + + text + 20:00 + + + + + text + 20:30 + + + + + text + 21:00 + + + + + text + 21:30 + + + + + text + 22:00 + + + + + text + 22:30 + + + + + text + 23:00 + + + + + text + 23:30 + + + + name + comboEnd + + + editable + true + + + duplicatesEnabled + false + + + + QLabel + + name + TextLabel3_2 + + + text + End + + + + QCheckBox + + name + checkAllDay + + + text + All day + + + + QLabel + + name + TextLabel3_2_2 + + + text + Time zone: + + + + TimeZoneSelector + + name + timezone + + + + QCheckBox + + name + checkAlarm + + + enabled + true + + + autoMask + false + + + text + &Alarm + + + checked + false + + + + QSpinBox + + name + spinAlarm + + + enabled + false + + + suffix + minutes + + + maxValue + 180 + + + minValue + 0 + + + lineStep + 5 + + + value + 5 + + + + QComboBox + + + text + Silent + + + + + text + Loud + + + + name + comboSound + + + enabled + false + + + + QLabel + + name + lblRepeat + + + text + Repeat + + + + QToolButton + + name + cmdRepeat + + + focusPolicy + TabFocus + + + text + No Repeat... + + + + QMultiLineEdit + + name + editNote + + + + + + + TimeZoneSelector +
qpe/tzselect.h
+ + 21 + 10 + + 0 + + 7 + 1 + + image0 +
+ + CategorySelect +
qpe/categoryselect.h
+ + -1 + -1 + + 0 + + 7 + 1 + + image1 +
+
+ + + image0 + 789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523250004143a55a6b2e0026630c4f + + + image1 + 789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758 + + + + + checkAlarm + toggled(bool) + spinAlarm + setEnabled(bool) + + + comboEnd + activated(const QString&) + DateEntryBase + endTimeChanged( const QString & ) + + + cmdRepeat + clicked() + DateEntryBase + slotRepeat() + + + comboStart + activated(int) + DateEntryBase + startTimeChanged( int ) + + + checkAllDay + toggled(bool) + comboEnd + setDisabled(bool) + + + checkAlarm + toggled(bool) + comboSound + setEnabled(bool) + + + checkAllDay + toggled(bool) + comboStart + setDisabled(bool) + + endDateChanged( const QString & ) + endDateChanged( int, int, int ) + endTimeChanged( const QString & ) + slotRepeat() + slotWait( int ) + startDateChanged( const QString & ) + startDateChanged(int, int, int) + startTimeChanged( int ) + typeChanged( const QString & ) + tzexecute(void) + +
diff --git a/core/pim/datebook/dateentryimpl.cpp b/core/pim/datebook/dateentryimpl.cpp new file mode 100644 index 0000000..1122f79 --- a/dev/null +++ b/core/pim/datebook/dateentryimpl.cpp @@ -0,0 +1,474 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "dateentryimpl.h" +#include "repeatentry.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Constructs a DateEntry which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ + +DateEntry::DateEntry( bool startOnMonday, const QDateTime &start, + const QDateTime &end, bool whichClock, QWidget* parent, + const char* name ) + : DateEntryBase( parent, name ), + ampm( whichClock ), + startWeekOnMonday( startOnMonday ) +{ + init(); + setDates(start,end); +} + +static void addOrPick( QComboBox* combo, const QString& t ) +{ + for (int i=0; icount(); i++) { + if ( combo->text(i) == t ) { + combo->setCurrentItem(i); + return; + } + } + combo->setEditText(t); +} + +DateEntry::DateEntry( bool startOnMonday, const Event &event, bool whichClock, + QWidget* parent, const char* name ) + : DateEntryBase( parent, name ), + ampm( whichClock ), + startWeekOnMonday( startOnMonday ) +{ + init(); + setDates(event.start(),event.end()); + comboCategory->setCategories( event.categories(), "Calendar", tr("Calendar") ); + if(!event.description().isEmpty()) + addOrPick( comboDescription, event.description() ); + if(!event.location().isEmpty()) + addOrPick( comboLocation, event.location() ); + checkAlarm->setChecked( event.hasAlarm() ); + checkAllDay->setChecked( event.type() == Event::AllDay ); + if(!event.notes().isEmpty()) + editNote->setText(event.notes()); + spinAlarm->setValue(event.alarmTime()); + if ( event.alarmSound() != Event::Silent ) + comboSound->setCurrentItem( 1 ); + if ( event.hasRepeat() ) { + rp = event.repeatPattern(); + cmdRepeat->setText( tr("Repeat...") ); + } + setRepeatLabel(); +} + +void DateEntry::setDates( const QDateTime& s, const QDateTime& e ) +{ + int shour, + ehour; + QString strStart, + strEnd; + startDate = s.date(); + endDate = e.date(); + startTime = s.time(); + endTime = e.time(); + startDateChanged( s.date().year(), s.date().month(), s.date().day() ); + if ( ampm ) { + shour = s.time().hour(); + ehour = e.time().hour(); + if ( shour >= 12 ) { + if ( shour > 12 ) + shour -= 12; + strStart.sprintf( "%d:%02d PM", shour, s.time().minute() ); + } else { + if ( shour == 0 ) + shour = 12; + strStart.sprintf( "%d:%02d AM", shour, s.time().minute() ); + } + if ( ehour == 24 && e.time().minute() == 0 ) { + strEnd = "11:59 PM"; // or "midnight" + } else if ( ehour >= 12 ) { + if ( ehour > 12 ) + ehour -= 12; + strEnd.sprintf( "%d:%02d PM", ehour, e.time().minute() ); + } else { + if ( ehour == 0 ) + ehour = 12; + strEnd.sprintf( "%d:%02d AM", ehour, e.time().minute() ); + } + } else { + strStart.sprintf( "%02d:%02d", s.time().hour(), s.time().minute() ); + strEnd.sprintf( "%02d:%02d", e.time().hour(), e.time().minute() ); + } + addOrPick(comboStart, strStart ); + endDateChanged( e.date().year(), e.date().month(), e.date().day() ); + addOrPick(comboEnd, strEnd ); +} + +void DateEntry::init() +{ + comboDescription->setInsertionPolicy(QComboBox::AtCurrent); + comboLocation->setInsertionPolicy(QComboBox::AtCurrent); + + initCombos(); + QPopupMenu *m1 = new QPopupMenu( this ); + startPicker = new DateBookMonth( m1, 0, TRUE ); + m1->insertItem( startPicker ); + buttonStart->setPopup( m1 ); + connect( startPicker, SIGNAL( dateClicked( int, int, int ) ), + this, SLOT( startDateChanged( int, int, int ) ) ); + + //Let start button change both start and end dates + connect( startPicker, SIGNAL( dateClicked( int, int, int ) ), + this, SLOT( endDateChanged( int, int, int ) ) ); + connect( qApp, SIGNAL( clockChanged( bool ) ), + this, SLOT( slotChangeClock( bool ) ) ); + connect( qApp, SIGNAL(weekChanged(bool)), + this, SLOT(slotChangeStartOfWeek(bool)) ); + + QPopupMenu *m2 = new QPopupMenu( this ); + endPicker = new DateBookMonth( m2, 0, TRUE ); + m2->insertItem( endPicker ); + buttonEnd->setPopup( m2 ); + connect( endPicker, SIGNAL( dateClicked( int, int, int ) ), + this, SLOT( endDateChanged( int, int, int ) ) ); +} + +/* + * Destroys the object and frees any allocated resources + */ +DateEntry::~DateEntry() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * public slot + */ +void DateEntry::endDateChanged( int y, int m, int d ) +{ + endDate.setYMD( y, m, d ); + if ( endDate < startDate ) { + endDate = startDate; + } + + buttonEnd->setText( TimeString::shortDate( endDate ) ); + + endPicker->setDate( endDate.year(), endDate.month(), endDate.day() ); +} + +static QTime parseTime( const QString& s, bool ampm ) +{ + QTime tmpTime; + QStringList l = QStringList::split( ':', s ); + int hour = l[0].toInt(); + if ( ampm ) { + int i=0; + while (i='0' && l[1][i]<='9') + i++; + QString digits = l[1].left(i); + if ( l[1].contains( "PM", FALSE ) ) { + if ( hour != 12 ) + hour += 12; + } else { + if ( hour == 12 ) + hour = 0; + } + l[1] = digits; + } + int minute = l[1].toInt(); + if ( minute > 59 ) + minute = 59; + else if ( minute < 0 ) + minute = 0; + if ( hour > 23 ) { + hour = 23; + minute = 59; + } else if ( hour < 0 ) + hour = 0; + tmpTime.setHMS( hour, minute, 0 ); + return tmpTime; +} + +/* + * public slot + */ +void DateEntry::endTimeChanged( const QString &s ) +{ + QTime tmpTime = parseTime(s,ampm); + if ( endDate > startDate || tmpTime >= startTime ) { + endTime = tmpTime; + } else { + endTime = startTime; + comboEnd->setCurrentItem( comboStart->currentItem() ); + } +} + +/* + * public slot + */ +void DateEntry::startDateChanged( int y, int m, int d ) +{ + QDate prev = startDate; + startDate.setYMD( y, m, d ); + if ( rp.type == Event::Weekly && + startDate.dayOfWeek() != prev.dayOfWeek() ) { + // if we change the start of a weekly repeating event + // set the repeating day appropriately + char mask = 1 << (prev.dayOfWeek()-1); + rp.days &= (~mask); + rp.days |= 1 << (startDate.dayOfWeek()-1); + } + + buttonStart->setText( TimeString::shortDate( startDate ) ); + + // our pickers must be reset... + startPicker->setDate( y, m, d ); + endPicker->setDate( y, m, d ); +} + +/* + * public slot + */ +void DateEntry::startTimeChanged( int index ) +{ + startTime = parseTime(comboStart->text(index),ampm); + changeEndCombo( index ); +} +/* + * public slot + */ +void DateEntry::typeChanged( const QString &s ) +{ + bool b = s != "All Day"; + buttonStart->setEnabled( b ); + comboStart->setEnabled( b ); + comboEnd->setEnabled( b ); +} +/* + * public slot + */ +void DateEntry::changeEndCombo( int change ) +{ + if ( change + 2 < comboEnd->count() ) + change += 2; + comboEnd->setCurrentItem( change ); + endTimeChanged( comboEnd->currentText() ); +} + +void DateEntry::slotRepeat() +{ + // Work around for compiler Bug.. + RepeatEntry *e; + + // it is better in my opinion to just grab this from the mother, + // since, this dialog doesn't need to keep track of it... + if ( rp.type != Event::NoRepeat ) + e = new RepeatEntry( startWeekOnMonday, rp, startDate, this); + else + e = new RepeatEntry( startWeekOnMonday, startDate, this ); + +#if defined(Q_WS_QWS) || defined(_WS_QWS_) + e->showMaximized(); +#endif + if ( e->exec() ) { + rp = e->repeatPattern(); + setRepeatLabel(); + } +} + +void DateEntry::slotChangeStartOfWeek( bool onMonday ) +{ + startWeekOnMonday = onMonday; +} + +Event DateEntry::event() +{ + Event ev; + Event::SoundTypeChoice st; + ev.setDescription( comboDescription->currentText() ); + ev.setLocation( comboLocation->currentText() ); + ev.setCategories( comboCategory->currentCategories() ); + ev.setType( checkAllDay->isChecked() ? Event::AllDay : Event::Normal ); + if ( startDate > endDate ) { + QDate tmp = endDate; + endDate = startDate; + startDate = tmp; + } + startTime = parseTime( comboStart->currentText(), ampm ); + endTime = parseTime( comboEnd->currentText(), ampm ); + if ( startTime > endTime && endDate == startDate ) { + QTime tmp = endTime; + endTime = startTime; + startTime = tmp; + } + // don't set the time if theres no need too + if ( ev.type() == Event::AllDay ) { + startTime.setHMS( 0, 0, 0 ); + endTime.setHMS( 23, 59, 59 ); + } + + // adjust start and end times based on timezone + QDateTime start( startDate, startTime ); + QDateTime end( endDate, endTime ); + time_t start_utc, end_utc; + +// qDebug( "tz: %s", timezone->currentZone().latin1() ); + + // get real timezone + QString realTZ; + realTZ = QString::fromLocal8Bit( getenv("TZ") ); + + // set timezone + if ( setenv( "TZ", timezone->currentZone(), true ) != 0 ) + qWarning( "There was a problem setting the timezone." ); + + // convert to UTC based on selected TZ (calling tzset internally) + start_utc = TimeConversion::toUTC( start ); + end_utc = TimeConversion::toUTC( end ); + + // done playing around... put it all back + unsetenv( "TZ" ); + if ( !realTZ.isNull() ) + if ( setenv( "TZ", realTZ, true ) != 0 ) + qWarning( "There was a problem setting the timezone." ); + + // convert UTC to local time (calling tzset internally) + ev.setStart( TimeConversion::fromUTC( start_utc ) ); + ev.setEnd( TimeConversion::fromUTC( end_utc ) ); + + // we only have one type of sound at the moment... LOUD!!! + if ( comboSound->currentItem() != 0 ) + st = Event::Loud; + else + st = Event::Silent; + ev.setAlarm( checkAlarm->isChecked(), spinAlarm->value(), st ); + if ( rp.type != Event::NoRepeat ) + ev.setRepeat( TRUE, rp ); + ev.setNotes( editNote->text() ); + return ev; +} + +void DateEntry::setRepeatLabel() +{ + + switch( rp.type ) { + case Event::Daily: + cmdRepeat->setText( tr("Daily...") ); + break; + case Event::Weekly: + cmdRepeat->setText( tr("Weekly...") ); + break; + case Event::MonthlyDay: + case Event::MonthlyDate: + cmdRepeat->setText( tr("Monthly...") ); + break; + case Event::Yearly: + cmdRepeat->setText( tr("Yearly...") ); + break; + default: + cmdRepeat->setText( tr("No Repeat...") ); + } +} + +void DateEntry::setAlarmEnabled( bool alarmPreset, int presetTime, Event::SoundTypeChoice sound ) +{ + checkAlarm->setChecked( alarmPreset ); + spinAlarm->setValue( presetTime ); + if ( sound != Event::Silent ) + comboSound->setCurrentItem( 1 ); + else + comboSound->setCurrentItem( 0 ); +} + +void DateEntry::initCombos() +{ + comboStart->clear(); + comboEnd->clear(); + if ( ampm ) { + for ( int i = 0; i < 24; i++ ) { + if ( i == 0 ) { + comboStart->insertItem( "12:00 AM" ); + comboStart->insertItem( "12:30 AM" ); + comboEnd->insertItem( "12:00 AM" ); + comboEnd->insertItem( "12:30 AM" ); + } else if ( i == 12 ) { + comboStart->insertItem( "12:00 PM" ); + comboStart->insertItem( "12:30 PM" ); + comboEnd->insertItem( "12:00 PM" ); + comboEnd->insertItem( "12:30 PM" ); + } else if ( i > 12 ) { + comboStart->insertItem( QString::number( i - 12 ) + ":00 PM" ); + comboStart->insertItem( QString::number( i - 12 ) + ":30 PM" ); + comboEnd->insertItem( QString::number( i - 12 ) + ":00 PM" ); + comboEnd->insertItem( QString::number( i - 12 ) + ":30 PM" ); + } else { + comboStart->insertItem( QString::number( i) + ":00 AM" ); + comboStart->insertItem( QString::number( i ) + ":30 AM" ); + comboEnd->insertItem( QString::number( i ) + ":00 AM" ); + comboEnd->insertItem( QString::number( i ) + ":30 AM" ); + } + } + } else { + for ( int i = 0; i < 24; i++ ) { + if ( i < 10 ) { + comboStart->insertItem( QString("0") + + QString::number(i) + ":00" ); + comboStart->insertItem( QString("0") + + QString::number(i) + ":30" ); + comboEnd->insertItem( QString("0") + + QString::number(i) + ":00" ); + comboEnd->insertItem( QString("0") + + QString::number(i) + ":30" ); + } else { + comboStart->insertItem( QString::number(i) + ":00" ); + comboStart->insertItem( QString::number(i) + ":30" ); + comboEnd->insertItem( QString::number(i) + ":00" ); + comboEnd->insertItem( QString::number(i) + ":30" ); + } + } + } +} + +void DateEntry::slotChangeClock( bool whichClock ) +{ + ampm = whichClock; + initCombos(); + setDates( QDateTime( startDate, startTime ), QDateTime( endDate, endTime ) ); +} diff --git a/core/pim/datebook/dateentryimpl.h b/core/pim/datebook/dateentryimpl.h new file mode 100644 index 0000000..785af7a --- a/dev/null +++ b/core/pim/datebook/dateentryimpl.h @@ -0,0 +1,71 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef DATEENTRY_H +#define DATEENTRY_H + +#include "dateentry.h" + +#include + +#include + +class DateBookMonth; + +class DateEntry : public DateEntryBase +{ + Q_OBJECT + +public: + DateEntry( bool startOnMonday, const QDateTime &start, + const QDateTime &end, bool whichClock = FALSE, + QWidget* parent = 0, const char* name = 0 ); + DateEntry( bool startOnMonday, const Event &event, bool whichCLock = FALSE, + QWidget* parent = 0, const char* name = 0 ); + ~DateEntry(); + + Event event(); + void setAlarmEnabled( bool alarmPreset, int presetTime, Event::SoundTypeChoice ); + +public slots: + void endDateChanged( int, int, int ); + void endTimeChanged( const QString & ); + void startDateChanged(int, int, int); + void startTimeChanged( int index ); + void typeChanged( const QString & ); + void changeEndCombo( int change ); + void slotRepeat(); + void slotChangeClock( bool ); + void slotChangeStartOfWeek( bool ); + +private: + void init(); + void initCombos(); + void setDates( const QDateTime& s, const QDateTime& e ); + void setRepeatLabel(); + + DateBookMonth *startPicker, *endPicker; + QDate startDate, endDate; + QTime startTime, endTime; + Event::RepeatPattern rp; + bool ampm; + bool startWeekOnMonday; +}; + +#endif // DATEENTRY_H diff --git a/core/pim/datebook/main.cpp b/core/pim/datebook/main.cpp new file mode 100644 index 0000000..caa5fb6 --- a/dev/null +++ b/core/pim/datebook/main.cpp @@ -0,0 +1,38 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "datebook.h" +#include + + +int main( int argc, char **argv ) +{ + QPEApplication a( argc, argv ); + + DateBook e; + QObject::connect( &a, SIGNAL( flush() ), &e, SLOT( flush() ) ); + QObject::connect( &a, SIGNAL( reload() ), &e, SLOT( reload() ) ); + + + e.setCaption( DateBook::tr("Calendar") ); + a.showMainWidget(&e); + + return a.exec(); +} diff --git a/core/pim/datebook/qpe-datebook.control b/core/pim/datebook/qpe-datebook.control new file mode 100644 index 0000000..c6ab81a --- a/dev/null +++ b/core/pim/datebook/qpe-datebook.control @@ -0,0 +1,9 @@ +Files: bin/datebook apps/Applications/datebook.desktop +Priority: optional +Section: qpe/applications +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: A datebook/appointment manager + A datebook/appointment manager for the Qtopia environment. diff --git a/core/pim/datebook/repeatentry.cpp b/core/pim/datebook/repeatentry.cpp new file mode 100644 index 0000000..5637c4d --- a/dev/null +++ b/core/pim/datebook/repeatentry.cpp @@ -0,0 +1,595 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "repeatentry.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +// Global Templates for use in setting up the repeat label... +const QString strDayTemplate = QObject::tr("Every"); +const QString strYearTemplate = QObject::tr("%1 %2 every "); +const QString strMonthDateTemplate = QObject::tr("The %1 every "); +const QString strMonthDayTemplate = QObject::tr("The %1 %1 of every"); +const QString strWeekTemplate = QObject::tr("Every "); +const QString dayLabel[] = { QObject::tr("Monday"), + QObject::tr("Tuesday"), + QObject::tr("Wednesday"), + QObject::tr("Thursday"), + QObject::tr("Friday"), + QObject::tr("Saturday"), + QObject::tr("Sunday") }; + + +static QString numberPlacing( int x ); // return the proper word format for + // x (1st, 2nd, etc) +static int week( const QDate &dt ); // what week in the month is dt? + +RepeatEntry::RepeatEntry( bool startOnMonday, + const QDate &newStart, QWidget *parent, + const char *name, bool modal, WFlags fl ) + : RepeatEntryBase( parent, name, modal, fl ), + start( newStart ), + currInterval( NONE ), + startWeekOnMonday( startOnMonday ) +{ + init(); + fraType->setButton( currInterval ); + chkNoEnd->setChecked( TRUE ); + setupNone(); +} + +RepeatEntry::RepeatEntry( bool startOnMonday, const Event::RepeatPattern &rp, + const QDate &startDate, + QWidget *parent, const char *name, bool modal, + WFlags fl ) + : RepeatEntryBase( parent, name, modal, fl ), + start( startDate ), + end( rp.endDate() ), + startWeekOnMonday( startOnMonday ) +{ + // do some stuff with the repeat pattern + init(); + switch ( rp.type ) { + default: + case Event::NoRepeat: + currInterval = NONE; + setupNone(); + break; + case Event::Daily: + currInterval = DAY; + setupDaily(); + break; + case Event::Weekly: + currInterval = WEEK; + setupWeekly(); + int day, buttons; + for ( day = 0x01, buttons = 0; buttons < 7; + day = day << 1, buttons++ ) { + if ( rp.days & day ) { + if ( startWeekOnMonday ) + fraExtra->setButton( buttons ); + else { + if ( buttons == 7 ) + fraExtra->setButton( 0 ); + else + fraExtra->setButton( buttons + 1 ); + } + } + } + slotWeekLabel(); + break; + case Event::MonthlyDay: + currInterval = MONTH; + setupMonthly(); + fraExtra->setButton( 0 ); + slotMonthLabel( 0 ); + break; + case Event::MonthlyDate: + currInterval = MONTH; + setupMonthly(); + fraExtra->setButton( 1 ); + slotMonthLabel( 1 ); + break; + case Event::Yearly: + currInterval = YEAR; + setupYearly(); + break; + } + fraType->setButton( currInterval ); + spinFreq->setValue( rp.frequency ); + if ( !rp.hasEndDate ) { + cmdEnd->setText( RepeatEntryBase::tr("No End Date") ); + chkNoEnd->setChecked( TRUE ); + } else + cmdEnd->setText( TimeString::shortDate( end ) ); +} + +RepeatEntry::~RepeatEntry() +{ +} + +Event::RepeatPattern RepeatEntry::repeatPattern() +{ + QListIterator it( listRTypeButtons ); + QListIterator itExtra( listExtra ); + Event::RepeatPattern rpTmp; + int i; + for ( i = 0; *it; ++it, i++ ) { + if ( (*it)->isOn() ) { + switch ( i ) { + case NONE: + rpTmp.type = Event::NoRepeat; + break; + case DAY: + rpTmp.type = Event::Daily; + break; + case WEEK: + rpTmp.type = Event::Weekly; + rpTmp.days = 0; + int day; + for ( day = 1; *itExtra; ++itExtra, day = day << 1 ) { + if ( (*itExtra)->isOn() ) { + if ( startWeekOnMonday ) + rpTmp.days |= day; + else { + if ( day == 1 ) + rpTmp.days |= Event::SUN; + else + rpTmp.days |= day >> 1; + } + } + } + break; + case MONTH: + if ( cmdExtra1->isOn() ) + rpTmp.type = Event::MonthlyDay; + else if ( cmdExtra2->isOn() ) + rpTmp.type = Event::MonthlyDate; + // figure out the montly day... + rpTmp.position = week( start ); + break; + case YEAR: + rpTmp.type = Event::Yearly; + break; + } + break; // no need to keep looking! + } + } + rpTmp.frequency = spinFreq->value(); + rpTmp.hasEndDate = !chkNoEnd->isChecked(); + if ( rpTmp.hasEndDate ) { + rpTmp.setEndDate( end ); + } + // timestamp it... + rpTmp.createTime = time( NULL ); + return rpTmp; +} + +void RepeatEntry::slotSetRType( int rtype ) +{ + // now call the right function based on the type... + currInterval = static_cast(rtype); + switch ( currInterval ) { + case NONE: + setupNone(); + break; + case DAY: + setupDaily(); + break; + case WEEK: + setupWeekly(); + slotWeekLabel(); + break; + case MONTH: + setupMonthly(); + cmdExtra2->setOn( TRUE ); + slotMonthLabel( 1 ); + break; + case YEAR: + setupYearly(); + break; + } +} + +void RepeatEntry::setupNone() +{ + lblRepeat->setText( tr("No Repeat") ); + lblVar1->hide(); + lblVar2->hide(); + hideExtras(); + cmdEnd->hide(); + lblFreq->hide(); + lblEvery->hide(); + lblFreq->hide(); + spinFreq->hide(); + lblEnd->hide(); + lblWeekVar->hide(); +} + +void RepeatEntry::setupDaily() +{ + hideExtras(); + lblWeekVar->hide(); + spinFreq->setValue( 1 ); + lblFreq->setText( tr("day(s)") ); + lblVar2->show(); + showRepeatStuff(); + lblRepeat->setText( strDayTemplate ); + setupRepeatLabel( 1 ); +} + +void RepeatEntry::setupWeekly() +{ + // reshow the buttons... + fraExtra->setTitle( RepeatEntryBase::tr("Repeat On") ); + fraExtra->setExclusive( FALSE ); + fraExtra->show(); + if ( startWeekOnMonday ) { + cmdExtra1->setText( RepeatEntryBase::tr("Mon") ); + cmdExtra2->setText( RepeatEntryBase::tr("Tue") ); + cmdExtra3->setText( RepeatEntryBase::tr("Wed") ); + cmdExtra4->setText( RepeatEntryBase::tr("Thu") ); + cmdExtra5->setText( RepeatEntryBase::tr("Fri") ); + cmdExtra6->setText( RepeatEntryBase::tr("Sat") ); + cmdExtra7->setText( RepeatEntryBase::tr("Sun") ); + } else { + cmdExtra1->setText( RepeatEntryBase::tr("Sun") ); + cmdExtra2->setText( RepeatEntryBase::tr("Mon") ); + cmdExtra3->setText( RepeatEntryBase::tr("Tue") ); + cmdExtra4->setText( RepeatEntryBase::tr("Wed") ); + cmdExtra5->setText( RepeatEntryBase::tr("Thu") ); + cmdExtra6->setText( RepeatEntryBase::tr("Fri") ); + cmdExtra7->setText( RepeatEntryBase::tr("Sat") ); + } + // I hope clustering these improve performance.... + cmdExtra1->setOn( FALSE ); + cmdExtra2->setOn( FALSE ); + cmdExtra3->setOn( FALSE ); + cmdExtra4->setOn( FALSE ); + cmdExtra5->setOn( FALSE ); + cmdExtra6->setOn( FALSE ); + cmdExtra7->setOn( FALSE ); + + cmdExtra1->show(); + cmdExtra2->show(); + cmdExtra3->show(); + cmdExtra4->show(); + cmdExtra5->show(); + cmdExtra6->show(); + cmdExtra7->show(); + + lblWeekVar->show(); + spinFreq->setValue( 1 ); + // might as well set the day too... + if ( startWeekOnMonday ) { + fraExtra->setButton( start.dayOfWeek() - 1 ); + } else { + fraExtra->setButton( start.dayOfWeek() % 7 ); + } + lblFreq->setText( tr("week(s)") ); + lblVar2->show(); + showRepeatStuff(); + setupRepeatLabel( 1 ); +} + +void RepeatEntry::setupMonthly() +{ + hideExtras(); + lblWeekVar->hide(); + fraExtra->setTitle( tr("Repeat By") ); + fraExtra->setExclusive( TRUE ); + fraExtra->show(); + cmdExtra1->setText( tr("Day") ); + cmdExtra1->show(); + cmdExtra2->setText( tr("Date") ); + cmdExtra2->show(); + spinFreq->setValue( 1 ); + lblFreq->setText( tr("month(s)") ); + lblVar2->show(); + showRepeatStuff(); + setupRepeatLabel( 1 ); +} + +void RepeatEntry::setupYearly() +{ + hideExtras(); + lblWeekVar->hide(); + spinFreq->setValue( 1 ); + lblFreq->setText( tr("year(s)") ); + lblFreq->show(); + lblFreq->show(); + showRepeatStuff(); + lblVar2->show(); + QString strEvery = strYearTemplate.arg( start.monthName(start.month()) ).arg( numberPlacing(start.day()) ); + lblRepeat->setText( strEvery ); + setupRepeatLabel( 1 ); + +} + +void RepeatEntry::init() +{ + QPopupMenu *m1 = new QPopupMenu( this ); + repeatPicker = new DateBookMonth( m1, 0, TRUE ); + m1->insertItem( repeatPicker ); + cmdEnd->setPopup( m1 ); + cmdEnd->setPopupDelay( 0 ); + + QObject::connect( repeatPicker, SIGNAL(dateClicked(int, int, int)), + this, SLOT(endDateChanged(int, int, int)) ); + QObject::connect( qApp, SIGNAL(weekChanged(bool)), + this, SLOT(slotChangeStartOfWeek(bool)) ); + + listRTypeButtons.setAutoDelete( TRUE ); + listRTypeButtons.append( cmdNone ); + listRTypeButtons.append( cmdDay ); + listRTypeButtons.append( cmdWeek ); + listRTypeButtons.append( cmdMonth ); + listRTypeButtons.append( cmdYear ); + + listExtra.setAutoDelete( TRUE ); + listExtra.append( cmdExtra1 ); + listExtra.append( cmdExtra2 ); + listExtra.append( cmdExtra3 ); + listExtra.append( cmdExtra4 ); + listExtra.append( cmdExtra5 ); + listExtra.append( cmdExtra6 ); + listExtra.append( cmdExtra7 ); +} + +void RepeatEntry::slotNoEnd( bool unused ) +{ + // if the item was toggled, then go ahead and set it to the maximum date + if ( unused ) { + end.setYMD( 3000, 12, 31 ); + cmdEnd->setText( RepeatEntryBase::tr("No End Date") ); + } else { + end = start; + cmdEnd->setText( TimeString::shortDate(end) ); + } +} + +void RepeatEntry::endDateChanged( int y, int m, int d ) +{ + end.setYMD( y, m, d ); + if ( end < start ) + end = start; + cmdEnd->setText( TimeString::shortDate( end ) ); + repeatPicker->setDate( end.year(), end.month(), end.day() ); +} + +void RepeatEntry::setupRepeatLabel( const QString &s ) +{ + lblVar1->setText( s ); +} + +void RepeatEntry::setupRepeatLabel( int x ) +{ + // change the spelling based on the value of x + QString strVar2; + + if ( x > 1 ) + lblVar1->show(); + else + lblVar1->hide(); + + switch ( currInterval ) { + case NONE: + break; + case DAY: + if ( x > 1 ) + strVar2 = tr( "days" ); + else + strVar2 = tr( "day" ); + break; + case WEEK: + if ( x > 1 ) + strVar2 = tr( "weeks" ); + else + strVar2 = tr( "week" ); + break; + case MONTH: + if ( x > 1 ) + strVar2 = RepeatEntryBase::tr( "months" ); + else + strVar2 = tr( "month" ); + break; + case YEAR: + if ( x > 1 ) + strVar2 = RepeatEntryBase::tr( "years" ); + else + strVar2 = tr( "year" ); + break; + } + if ( !strVar2.isNull() ) + lblVar2->setText( strVar2 ); +} + +void RepeatEntry::showRepeatStuff() +{ + cmdEnd->show(); + chkNoEnd->show(); + lblFreq->show(); + lblEvery->show(); + lblFreq->show(); + spinFreq->show(); + lblEnd->show(); + lblRepeat->setText( RepeatEntryBase::tr("Every") ); +} + +void RepeatEntry::slotWeekLabel() +{ + QString str; + QListIterator it( listExtra ); + unsigned int i; + unsigned int keepMe; + bool bNeedCarriage = FALSE; + // don't do something we'll regret!!! + if ( currInterval != WEEK ) + return; + + if ( startWeekOnMonday ) + keepMe = start.dayOfWeek() - 1; + else + keepMe = start.dayOfWeek() % 7; + + QStringList list; + for ( i = 0; *it; ++it, i++ ) { + // a crazy check, if you are repeating weekly, the current day + // must be selected!!! + if ( i == keepMe && !( (*it)->isOn() ) ) + (*it)->setOn( TRUE ); + if ( (*it)->isOn() ) { + if ( startWeekOnMonday ) + list.append( dayLabel[i] ); + else { + if ( i == 0 ) + list.append( dayLabel[6] ); + else + list.append( dayLabel[i - 1] ); + } + } + } + QStringList::Iterator itStr; + for ( i = 0, itStr = list.begin(); itStr != list.end(); ++itStr, i++ ) { + if ( i == 3 ) + bNeedCarriage = TRUE; + else + bNeedCarriage = FALSE; + if ( str.isNull() ) + str = *itStr; + else if ( i == list.count() - 1 ) { + if ( i < 2 ) + str += tr(" and ") + *itStr; + else { + if ( bNeedCarriage ) + str += tr( ",\nand " ) + *itStr; + else + str += tr( ", and " ) + *itStr; + } + } else { + if ( bNeedCarriage ) + str += ",\n" + *itStr; + else + str += ", " + *itStr; + } + } + str = str.prepend( "on " ); + lblWeekVar->setText( str ); +} + +void RepeatEntry::slotMonthLabel( int type ) +{ + QString str; + if ( currInterval != MONTH || type > 1 ) + return; + if ( type == 1 ) + str = strMonthDateTemplate.arg( numberPlacing(start.day()) ); + else + str = strMonthDayTemplate.arg( numberPlacing(week(start))) + .arg( dayLabel[start.dayOfWeek() - 1] ); + lblRepeat->setText( str ); +} + +void RepeatEntry::slotChangeStartOfWeek( bool onMonday ) +{ + startWeekOnMonday = onMonday; + // we need to make this unintrusive as possible... + int saveSpin = spinFreq->value(); + char days = 0; + int day; + QListIterator itExtra( listExtra ); + for ( day = 1; *itExtra; ++itExtra, day = day << 1 ) { + if ( (*itExtra)->isOn() ) { + if ( !startWeekOnMonday ) + days |= day; + else { + if ( day == 1 ) + days |= Event::SUN; + else + days |= day >> 1; + } + } + } + setupWeekly(); + spinFreq->setValue( saveSpin ); + int buttons; + for ( day = 0x01, buttons = 0; buttons < 7; + day = day << 1, buttons++ ) { + if ( days & day ) { + if ( startWeekOnMonday ) + fraExtra->setButton( buttons ); + else { + if ( buttons == 7 ) + fraExtra->setButton( 0 ); + else + fraExtra->setButton( buttons + 1 ); + } + } + } + slotWeekLabel(); +} + +static int week( const QDate &start ) +{ + // figure out the week... + int stop = start.day(), + sentinel = start.dayOfWeek(), + dayOfWeek = QDate( start.year(), start.month(), 1 ).dayOfWeek(), + week = 1, + i; + for ( i = 1; i < stop; i++ ) { + if ( dayOfWeek++ == sentinel ) + week++; + if ( dayOfWeek > 7 ) + dayOfWeek = 0; + } + return week; +} + +static QString numberPlacing( int x ) +{ + // I hope this works in other languages besides english... + QString str = QString::number( x ); + switch ( x % 10 ) { + case 1: + str += QWidget::tr( "st" ); + break; + case 2: + str += QWidget::tr( "nd" ); + break; + case 3: + str += QWidget::tr( "rd" ); + break; + default: + str += QWidget::tr( "th" ); + break; + } + return str; +} diff --git a/core/pim/datebook/repeatentry.h b/core/pim/datebook/repeatentry.h new file mode 100644 index 0000000..949fecd --- a/dev/null +++ b/core/pim/datebook/repeatentry.h @@ -0,0 +1,98 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef REPEATENTRY_H +#define REPEATENTRY_H + +#include "repeatentrybase.h" + +#include + +#include +#include +#include +#include +#include + +class DateBookMonth; + +class RepeatEntry : public RepeatEntryBase +{ + Q_OBJECT +public: + RepeatEntry( bool startOnMonday, + const QDate &start, QWidget *parent = 0, const char *name = 0, + bool modal = TRUE, WFlags fl = 0 ); + RepeatEntry( bool startOnMonday, + const Event::RepeatPattern &rp, const QDate &start, + QWidget *parent = 0, const char *name = 0, bool modal = TRUE, + WFlags fl = 0 ); + ~RepeatEntry(); + + Event::RepeatPattern repeatPattern(); + QDate endDate() { return end; }; + +public slots: + void slotSetRType( int ); + void endDateChanged( int, int, int ); + void slotNoEnd( bool unused ); + +private slots: + void setupRepeatLabel( const QString& ); + void setupRepeatLabel( int ); + void slotWeekLabel(); + void slotMonthLabel( int ); + void slotChangeStartOfWeek( bool onMonday ); + +private: + void setupNone(); + void setupDaily(); + void setupWeekly(); + void setupMonthly(); + void setupYearly(); + + enum repeatButtons { NONE, DAY, WEEK, MONTH, YEAR }; + void init(); + inline void hideExtras(); + void showRepeatStuff(); + + QList listRTypeButtons; + QList listExtra; + QDate start; // only used in one spot... + QDate end; + repeatButtons currInterval; + bool startWeekOnMonday; + DateBookMonth *repeatPicker; +}; + +inline void RepeatEntry::hideExtras() +{ + // hide the extra buttons... + fraExtra->hide(); + chkNoEnd->hide(); + QListIterator it( listExtra ); + for ( ; *it; ++it ) { + (*it)->hide(); + (*it)->setOn( FALSE ); + } + +} + +#endif diff --git a/core/pim/datebook/repeatentrybase.ui b/core/pim/datebook/repeatentrybase.ui new file mode 100644 index 0000000..9621d74 --- a/dev/null +++ b/core/pim/datebook/repeatentrybase.ui @@ -0,0 +1,713 @@ + +RepeatEntryBase +********************************************************************* +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +** $Id$ +** +********************************************************************* + + QDialog + + name + RepeatEntryBase + + + geometry + + 0 + 0 + 250 + 309 + + + + caption + Repeating Event + + + layoutMargin + + + layoutSpacing + + + + margin + 5 + + + spacing + 1 + + + QButtonGroup + + name + fraType + + + frameShape + NoFrame + + + frameShadow + Sunken + + + title + + + + exclusive + true + + + layoutMargin + + + layoutSpacing + + + + margin + 5 + + + spacing + 1 + + + QToolButton + + name + cmdNone + + + text + None + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdDay + + + text + Day + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdWeek + + + sizePolicy + + 1 + 0 + + + + text + Week + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdMonth + + + sizePolicy + + 1 + 0 + + + + text + Month + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdYear + + + text + Year + + + toggleButton + true + + + toggleButton + true + + + + + + QLayoutWidget + + name + Layout4 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + lblEvery + + + text + Every: + + + + QSpinBox + + name + spinFreq + + + minValue + 1 + + + + QLabel + + name + lblFreq + + + sizePolicy + + 1 + 1 + + + + text + Frequency + + + + + + QLayoutWidget + + name + Layout8 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + lblEnd + + + sizePolicy + + 1 + 0 + + + + text + End On: + + + + QToolButton + + name + cmdEnd + + + text + No End Date + + + + QCheckBox + + name + chkNoEnd + + + text + No End Date + + + + + + QButtonGroup + + name + fraExtra + + + sizePolicy + + 7 + 7 + + + + frameShape + Box + + + title + Repeat On + + + layoutMargin + + + layoutSpacing + + + + margin + 5 + + + spacing + 1 + + + QToolButton + + name + cmdExtra1 + + + text + Mon + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdExtra2 + + + text + Tue + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdExtra3 + + + text + Wed + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdExtra4 + + + text + Thu + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdExtra5 + + + text + Fri + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdExtra6 + + + text + Sat + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdExtra7 + + + text + Sun + + + toggleButton + true + + + toggleButton + true + + + + + + QFrame + + name + Frame3 + + + sizePolicy + + 7 + 7 + + + + frameShape + Box + + + frameShadow + Sunken + + + layoutMargin + + + layoutSpacing + + + + margin + 5 + + + spacing + 1 + + + QLayoutWidget + + name + Layout6 + + + layoutSpacing + + + + margin + 0 + + + spacing + 0 + + + QLabel + + name + lblRepeat + + + sizePolicy + + 1 + 3 + + + + text + Every + + + alignment + AlignTop|AlignLeft + + + hAlign + + + vAlign + + + + QLabel + + name + lblVar1 + + + sizePolicy + + 1 + 1 + + + + text + Var1 + + + alignment + AlignTop|AlignLeft + + + hAlign + + + vAlign + + + + QLabel + + name + lblVar2 + + + sizePolicy + + 4 + 1 + + + + text + Var 2 + + + alignment + AlignTop|AlignRight + + + hAlign + + + vAlign + + + + + + QLabel + + name + lblWeekVar + + + sizePolicy + + 1 + 7 + + + + text + WeekVar + + + alignment + AlignTop|AlignHCenter + + + hAlign + + + vAlign + + + + + + + + + chkNoEnd + toggled(bool) + cmdEnd + setDisabled(bool) + + + chkNoEnd + toggled(bool) + RepeatEntryBase + slotNoEnd(bool) + + + spinFreq + valueChanged(int) + lblVar1 + setNum(int) + + + spinFreq + valueChanged(int) + RepeatEntryBase + setupRepeatLabel( int ) + + + fraType + clicked(int) + RepeatEntryBase + slotSetRType( int ) + + + fraExtra + clicked(int) + RepeatEntryBase + slotMonthLabel( int ) + + + fraExtra + clicked(int) + RepeatEntryBase + slotWeekLabel() + + setupRepeatLabel( const QString & ) + setupRepeatLabel( int ) + slotMonthLabel( int ) + slotNoEnd(bool) + slotSetRType( int ) + slotWeekLabel() + + diff --git a/core/pim/todo/.cvsignore b/core/pim/todo/.cvsignore new file mode 100644 index 0000000..5ed04d8 --- a/dev/null +++ b/core/pim/todo/.cvsignore @@ -0,0 +1,4 @@ +moc_* +Makefile +todoentry.h +todoentry.cpp diff --git a/core/pim/todo/Makefile.in b/core/pim/todo/Makefile.in new file mode 100644 index 0000000..f3c5f0e --- a/dev/null +++ b/core/pim/todo/Makefile.in @@ -0,0 +1,201 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = $(QPEDIR)/bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = todolist +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = mainwindow.h \ + todotable.h \ + todoentryimpl.h +SOURCES = main.cpp \ + mainwindow.cpp \ + todotable.cpp \ + todoentryimpl.cpp +OBJECTS = main.o \ + mainwindow.o \ + todotable.o \ + todoentryimpl.o \ + todoentry.o +INTERFACES = todoentry.ui +UICDECLS = todoentry.h +UICIMPLS = todoentry.cpp +SRCMOC = moc_mainwindow.cpp \ + moc_todotable.cpp \ + moc_todoentryimpl.cpp \ + moc_todoentry.cpp +OBJMOC = moc_mainwindow.o \ + moc_todotable.o \ + moc_todoentryimpl.o \ + moc_todoentry.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake todo.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +main.o: main.cpp \ + mainwindow.h \ + $(QPEDIR)/include/qpe/qpeapplication.h + +mainwindow.o: mainwindow.cpp \ + mainwindow.h \ + todoentryimpl.h \ + todoentry.h \ + $(QPEDIR)/include/qpe/task.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/stringutil.h \ + todotable.h \ + $(QPEDIR)/include/qpe/categories.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/finddialog.h \ + $(QPEDIR)/include/qpe/global.h \ + $(QPEDIR)/include/qpe/ir.h \ + $(QPEDIR)/include/qpe/qpemenubar.h \ + $(QPEDIR)/include/qpe/qpemessagebox.h \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/qpetoolbar.h + +todotable.o: todotable.cpp \ + todotable.h \ + $(QPEDIR)/include/qpe/categories.h \ + $(QPEDIR)/include/qpe/task.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/stringutil.h \ + $(QPEDIR)/include/qpe/categoryselect.h \ + $(QPEDIR)/include/qpe/xmlreader.h + +todoentryimpl.o: todoentryimpl.cpp \ + todoentryimpl.h \ + todoentry.h \ + $(QPEDIR)/include/qpe/task.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/stringutil.h \ + $(QPEDIR)/include/qpe/categoryselect.h \ + $(QPEDIR)/include/qpe/datebookmonth.h \ + $(QPEDIR)/include/qpe/event.h \ + $(QPEDIR)/include/qpe/global.h \ + $(QPEDIR)/include/qpe/imageedit.h \ + $(QPEDIR)/include/qpe/timestring.h + +todoentry.h: todoentry.ui + $(UIC) todoentry.ui -o $(INTERFACE_DECL_PATH)/todoentry.h + +todoentry.cpp: todoentry.ui + $(UIC) todoentry.ui -i todoentry.h -o todoentry.cpp + +todoentry.o: todoentry.cpp \ + todoentry.h \ + todoentry.ui + +moc_mainwindow.o: moc_mainwindow.cpp \ + mainwindow.h + +moc_todotable.o: moc_todotable.cpp \ + todotable.h \ + $(QPEDIR)/include/qpe/categories.h \ + $(QPEDIR)/include/qpe/task.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/stringutil.h + +moc_todoentryimpl.o: moc_todoentryimpl.cpp \ + todoentryimpl.h \ + todoentry.h \ + $(QPEDIR)/include/qpe/task.h \ + $(QPEDIR)/include/qpe/palmtoprecord.h \ + $(QPEDIR)/include/qpe/stringutil.h + +moc_todoentry.o: moc_todoentry.cpp \ + todoentry.h + +moc_mainwindow.cpp: mainwindow.h + $(MOC) mainwindow.h -o moc_mainwindow.cpp + +moc_todotable.cpp: todotable.h + $(MOC) todotable.h -o moc_todotable.cpp + +moc_todoentryimpl.cpp: todoentryimpl.h + $(MOC) todoentryimpl.h -o moc_todoentryimpl.cpp + +moc_todoentry.cpp: todoentry.h + $(MOC) todoentry.h -o moc_todoentry.cpp + + diff --git a/core/pim/todo/main.cpp b/core/pim/todo/main.cpp new file mode 100644 index 0000000..4e1c8a1 --- a/dev/null +++ b/core/pim/todo/main.cpp @@ -0,0 +1,36 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "mainwindow.h" + +#include + +int main( int argc, char **argv ) +{ + QPEApplication a( argc, argv ); + + TodoWindow mw; + QObject::connect( &a, SIGNAL( flush() ), &mw, SLOT( flush() ) ); + QObject::connect( &a, SIGNAL( reload() ), &mw, SLOT( reload() ) ); + + a.showMainWidget(&mw); + + return a.exec(); +} diff --git a/core/pim/todo/mainwindow.cpp b/core/pim/todo/mainwindow.cpp new file mode 100644 index 0000000..fb85a09 --- a/dev/null +++ b/core/pim/todo/mainwindow.cpp @@ -0,0 +1,466 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "mainwindow.h" +#include "todoentryimpl.h" +#include "todotable.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +static QString todolistXMLFilename() +{ + return Global::applicationFileName("todolist","todolist.xml"); +} + +static QString categoriesXMLFilename() +{ + return Global::applicationFileName("todolist","categories.xml"); +} + +TodoWindow::TodoWindow( QWidget *parent, const char *name, WFlags f = 0 ) : + QMainWindow( parent, name, f ), syncing(FALSE) +{ +// QTime t; +// t.start(); + + setCaption( tr("Todo") ); + QString str; + table = new TodoTable( this ); + table->setColumnWidth( 2, 10 ); + table->setPaintingEnabled( FALSE ); + table->setUpdatesEnabled( FALSE ); + table->viewport()->setUpdatesEnabled( FALSE ); + + { + str = todolistXMLFilename(); + if ( str.isNull() ) + QMessageBox::critical( this, + tr("Out of Space"), + tr("Unable to create startup files\n" + "Free up some space\n" + "before you enter any data") ); + else + table->load( str ); + } + + // repeat for categories... + str = categoriesXMLFilename(); + if ( str.isNull() ) + QMessageBox::critical( this, + tr( "Out of Space" ), + tr( "Unable to create startup files\n" + "Free up some space\n" + "before you enter any data") ); + + setCentralWidget( table ); + setToolBarsMovable( FALSE ); + +// qDebug("after load: t=%d", t.elapsed() ); + + Config config( "todo" ); + config.setGroup( "View" ); + bool complete = config.readBoolEntry( "ShowComplete", true ); + table->setShowCompleted( complete ); + QString category = config.readEntry( "Category", QString::null ); + table->setShowCategory( category ); + + QPEToolBar *bar = new QPEToolBar( this ); + bar->setHorizontalStretchable( TRUE ); + + QPEMenuBar *mb = new QPEMenuBar( bar ); + + catMenu = new QPopupMenu( this ); + QPopupMenu *edit = new QPopupMenu( this ); + contextMenu = new QPopupMenu( this ); + + bar = new QPEToolBar( this ); + + QAction *a = new QAction( tr( "New Task" ), Resource::loadPixmap( "new" ), + QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), + this, SLOT( slotNew() ) ); + a->addTo( bar ); + a->addTo( edit ); + a = new QAction( tr( "Edit" ), Resource::loadIconSet( "edit" ), + QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), + this, SLOT( slotEdit() ) ); + a->addTo( bar ); + a->addTo( edit ); + a->addTo( contextMenu ); + a->setEnabled( FALSE ); + editAction = a; + a = new QAction( tr( "Delete" ), Resource::loadIconSet( "trash" ), + QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), + this, SLOT( slotDelete() ) ); + a->addTo( bar ); + a->addTo( edit ); + a->addTo( contextMenu ); + a->setEnabled( FALSE ); + deleteAction = a; + + if ( Ir::supported() ) { + a = new QAction( tr( "Beam" ), Resource::loadPixmap( "beam" ), + QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), + this, SLOT( slotBeam() ) ); + a->addTo( edit ); + a->addTo( bar ); + } + + a = new QAction( tr( "Find" ), Resource::loadIconSet( "mag" ), + QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), + this, SLOT( slotFind() ) ); + a->addTo( bar ); + a->addTo( edit ); + if ( table->numRows() ) + a->setEnabled( TRUE ); + else + a->setEnabled( FALSE ); + + //a->setEnabled( FALSE ); + findAction = a; +// qDebug("mainwindow #2: t=%d", t.elapsed() ); + + completedAction = new QAction( QString::null, tr("Completed tasks"), 0, this, 0, TRUE ); + + catMenu->setCheckable( true ); + populateCategories(); + + mb->insertItem( tr( "Task" ), edit ); + mb->insertItem( tr( "View" ), catMenu ); + + resize( 200, 300 ); + if ( table->numRows() > 0 ) + currentEntryChanged( 0, 0 ); + connect( table, SIGNAL( signalEdit() ), + this, SLOT( slotEdit() ) ); + connect( table, SIGNAL(signalShowMenu(const QPoint &)), + this, SLOT( slotShowPopup(const QPoint &)) ); + +// qDebug("mainwindow #3: t=%d", t.elapsed() ); + table->updateVisible(); + table->setUpdatesEnabled( TRUE ); + table->setPaintingEnabled( TRUE ); + table->viewport()->setUpdatesEnabled( TRUE ); + + connect( completedAction, SIGNAL( toggled(bool) ), this, SLOT( showCompleted(bool) ) ); + connect( catMenu, SIGNAL(activated(int)), this, SLOT(setCategory(int)) ); + connect( table, SIGNAL( currentChanged( int, int ) ), + this, SLOT( currentEntryChanged( int, int ) ) ); + +// qDebug("done: t=%d", t.elapsed() ); +} + +void TodoWindow::slotNew() +{ + if(syncing) { + QMessageBox::warning(this, tr("Todo"), + tr("Can not edit data, currently syncing")); + return; + } + + int id; + id = -1; + QArray ids; + ids = table->currentEntry().categories(); + if ( ids.count() ) + id = ids[0]; + NewTaskDialog e( id, this, 0, TRUE ); + + Task todo; + +#if defined(Q_WS_QWS) || defined(_WS_QWS_) + e.showMaximized(); +#endif + int ret = e.exec(); + + if ( ret == QDialog::Accepted ) { + table->setPaintingEnabled( false ); + todo = e.todoEntry(); + todo.assignUid(); + table->addEntry( todo ); + table->setPaintingEnabled( true ); + findAction->setEnabled( TRUE ); + } + // I'm afraid we must call this every time now, otherwise + // spend expensive time comparing all these strings... + populateCategories(); +} + +TodoWindow::~TodoWindow() +{ +} + +void TodoWindow::slotDelete() +{ + if(syncing) { + QMessageBox::warning(this, tr("Todo"), + tr("Can not edit data, currently syncing")); + return; + } + + if ( table->currentRow() == -1 ) + return; + + QString strName = table->text( table->currentRow(), 2 ).left( 30 ); + + if ( !QPEMessageBox::confirmDelete( this, tr( "Todo" ), strName ) ) + return; + + + + table->setPaintingEnabled( false ); + table->removeCurrentEntry(); + table->setPaintingEnabled( true ); + + if ( table->numRows() == 0 ) { + currentEntryChanged( -1, 0 ); + findAction->setEnabled( FALSE ); + } +} + +void TodoWindow::slotEdit() +{ + if(syncing) { + QMessageBox::warning(this, tr("Todo"), + tr("Can not edit data, currently syncing")); + return; + } + + Task todo = table->currentEntry(); + + NewTaskDialog e( todo, this, 0, TRUE ); + e.setCaption( tr( "Edit Task" ) ); + +#if defined(Q_WS_QWS) || defined(_WS_QWS_) + e.showMaximized(); +#endif + int ret = e.exec(); + + if ( ret == QDialog::Accepted ) { + table->setPaintingEnabled( false ); + todo = e.todoEntry(); + table->replaceCurrentEntry( todo ); + table->setPaintingEnabled( true ); + } + populateCategories(); + +} + +void TodoWindow::slotShowPopup( const QPoint &p ) +{ + contextMenu->popup( p ); +} + +void TodoWindow::showCompleted( bool s ) +{ + if ( !table->isUpdatesEnabled() ) + return; + table->setPaintingEnabled( false ); + table->setShowCompleted( s ); + table->setPaintingEnabled( true ); +} + +void TodoWindow::currentEntryChanged( int r, int ) +{ + if ( r != -1 && table->rowHeight( r ) > 0 ) { + editAction->setEnabled( TRUE ); + deleteAction->setEnabled( TRUE ); + } else { + editAction->setEnabled( FALSE ); + deleteAction->setEnabled( FALSE ); + } +} + +void TodoWindow::setCategory( int c ) +{ + if ( c <= 0 ) return; + if ( !table->isUpdatesEnabled() ) + return; + table->setPaintingEnabled( false ); + for ( unsigned int i = 1; i < catMenu->count(); i++ ) + catMenu->setItemChecked( i, c == (int)i ); + if ( c == 1 ) { + table->setShowCategory( QString::null ); + setCaption( tr("Todo") + " - " + tr( "All" ) ); + } else if ( c == (int)catMenu->count() - 1 ) { + table->setShowCategory( tr( "Unfiled" ) ); + setCaption( tr("Todo") + " - " + tr( "Unfiled" ) ); + } else { + QString cat = table->categories()[c - 2]; + table->setShowCategory( cat ); + setCaption( tr("Todo") + " - " + cat ); + } + table->setPaintingEnabled( true ); +} + +void TodoWindow::populateCategories() +{ + catMenu->clear(); + + completedAction->addTo( catMenu ); + completedAction->setOn( table->showCompleted() ); + + int id, + rememberId; + id = 1; + catMenu->insertItem( tr( "All" ), id++ ); +// catMenu->insertSeparator(); + QStringList categories = table->categories(); + categories.append( tr( "Unfiled" ) ); + for ( QStringList::Iterator it = categories.begin(); + it != categories.end(); ++it ) { + catMenu->insertItem( *it, id ); + if ( *it == table->showCategory() ) + rememberId = id; + ++id; + } + if ( table->showCategory().isEmpty() ) + setCategory( 1 ); + else + setCategory( rememberId ); +} + +void TodoWindow::reload() +{ + table->clear(); + table->load( todolistXMLFilename() ); + syncing = FALSE; +} + +void TodoWindow::flush() +{ + syncing = TRUE; + table->save( todolistXMLFilename() ); +} + +void TodoWindow::closeEvent( QCloseEvent *e ) +{ + if(syncing) { + /* no need to save if in the middle of syncing */ + e->accept(); + return; + } + + if ( table->save( todolistXMLFilename() ) ) { + e->accept(); + // repeat for categories... + // if writing configs fail, it will emit an + // error, but I feel that it is "ok" for us to exit + // espically since we aren't told if the write succeeded... + Config config( "todo" ); + config.setGroup( "View" ); + config.writeEntry( "ShowComplete", table->showCompleted() ); + config.writeEntry( "Category", table->showCategory() ); + } else { + if ( QMessageBox::critical( this, tr("Out of space"), + tr("Todo was unable\n" + "to save your changes.\n" + "Free up some space\n" + "and try again.\n" + "\nQuit Anyway?"), + QMessageBox::Yes|QMessageBox::Escape, + QMessageBox::No|QMessageBox::Default) + != QMessageBox::No ) + e->accept(); + else + e->ignore(); + } +} + +void TodoWindow::slotFind() +{ + // put everything back to view all for searching... + if ( !catMenu->isItemChecked( 0 ) ) + setCategory( 0 ); + + FindDialog dlg( "Todo List", this ); + QObject::connect( &dlg, + SIGNAL(signalFindClicked(const QString &, + bool, bool, int)), + table, + SLOT(slotDoFind(const QString&, bool, bool, int)) ); + QObject::connect( table, SIGNAL(signalNotFound()), &dlg, + SLOT(slotNotFound()) ); + QObject::connect( table, SIGNAL(signalWrapAround()), &dlg, + SLOT(slotWrapAround()) ); + dlg.exec(); + if ( table->numSelections() ) + table->clearSelection(); + table->clearFindRow(); +} + + +void TodoWindow::setDocument( const QString &filename ) +{ + if ( filename.find(".vcs") != int(filename.length()) - 4 ) return; + + QValueList tl = Task::readVCalendar( filename ); + for( QValueList::Iterator it = tl.begin(); it != tl.end(); ++it ) { + table->addEntry( *it ); + } +} + +static const char * beamfile = "/tmp/obex/todo.vcs"; + +void TodoWindow::slotBeam() +{ + unlink( beamfile ); // delete if exists + Task c = table->currentEntry(); + mkdir("/tmp/obex/", 0755); + Task::writeVCalendar( beamfile, c ); + Ir *ir = new Ir( this ); + connect( ir, SIGNAL( done( Ir * ) ), this, SLOT( beamDone( Ir * ) ) ); + QString description = c.description(); + ir->send( beamfile, description, "text/x-vCalendar" ); +} + +void TodoWindow::beamDone( Ir *ir ) +{ + delete ir; + unlink( beamfile ); +} diff --git a/core/pim/todo/mainwindow.h b/core/pim/todo/mainwindow.h new file mode 100644 index 0000000..f4fcd1b --- a/dev/null +++ b/core/pim/todo/mainwindow.h @@ -0,0 +1,73 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +class TodoTable; +class QAction; +class QPopupMenu; +class Ir; + +class TodoWindow : public QMainWindow +{ + Q_OBJECT + +public: + TodoWindow( QWidget *parent = 0, const char *name = 0, WFlags f = 0 ); + ~TodoWindow(); + +public slots: + void flush(); + void reload(); + +protected slots: + void slotNew(); + void slotDelete(); + void slotEdit(); + void slotShowPopup( const QPoint & ); + void showCompleted( bool ); + void currentEntryChanged( int r, int c ); + void setCategory( int ); + void slotFind(); + void setDocument( const QString & ); + void slotBeam(); + void beamDone( Ir * ); + +protected: + void closeEvent( QCloseEvent *e ); + +private: + void populateCategories(); + +private: + TodoTable *table; + QAction *editAction, + *deleteAction, + *findAction, + * completedAction; + QPopupMenu *contextMenu, *catMenu; + + bool syncing; +}; + +#endif diff --git a/core/pim/todo/qpe-todo.control b/core/pim/todo/qpe-todo.control new file mode 100644 index 0000000..80195a0 --- a/dev/null +++ b/core/pim/todo/qpe-todo.control @@ -0,0 +1,9 @@ +Files: bin/todolist apps/Applications/todo.desktop +Priority: optional +Section: qpe/applications +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: TODO-list manager + A Todo-list manager for the Qtopia environment. diff --git a/core/pim/todo/todo.pro b/core/pim/todo/todo.pro new file mode 100644 index 0000000..e28ea1c --- a/dev/null +++ b/core/pim/todo/todo.pro @@ -0,0 +1,19 @@ +TEMPLATE = app +CONFIG = qt warn_on release +DESTDIR = $(QPEDIR)/bin +HEADERS = mainwindow.h \ + todotable.h \ + todoentryimpl.h +SOURCES = main.cpp \ + mainwindow.cpp \ + todotable.cpp \ + todoentryimpl.cpp + +INTERFACES = todoentry.ui + +TARGET = todolist +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe + +TRANSLATIONS = ../i18n/de/todolist.ts diff --git a/core/pim/todo/todoentry.ui b/core/pim/todo/todoentry.ui new file mode 100644 index 0000000..c735e76 --- a/dev/null +++ b/core/pim/todo/todoentry.ui @@ -0,0 +1,266 @@ + +NewTaskDialogBase +********************************************************************* +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +********************************************************************* + + QDialog + + name + NewTaskDialogBase + + + geometry + + 0 + 0 + 249 + 321 + + + + caption + New Task + + + layoutMargin + + + layoutSpacing + + + + margin + 0 + + + spacing + 0 + + + QLayoutWidget + + name + Layout4 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + TextLabel2 + + + text + Priority: + + + + QComboBox + + + text + 1 - Very High + + + + + text + 2 - High + + + + + text + 3 - Normal + + + + + text + 4 - Low + + + + + text + 5 - Very Low + + + + name + comboPriority + + + sizePolicy + + 7 + 0 + + + + currentItem + 2 + + + + + + QLayoutWidget + + name + Layout3 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + TextLabel3 + + + frameShape + NoFrame + + + text + Category: + + + + CategorySelect + + name + comboCategory + + + + + + QLayoutWidget + + name + Layout4 + + + + margin + 0 + + + spacing + 6 + + + QCheckBox + + name + checkCompleted + + + text + &Completed + + + + QCheckBox + + name + checkDate + + + text + D&ue + + + + QPushButton + + name + buttonDate + + + enabled + false + + + text + 1 Jan 2001 + + + + + + QMultiLineEdit + + name + txtTodo + + + + + + + CategorySelect +
qpe/categoryselect.h
+ + -1 + -1 + + 0 + + 7 + 1 + + image0 +
+
+ + + image0 + 789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758 + + + + + checkDate + toggled(bool) + buttonDate + setEnabled(bool) + + dateChanged( const QString & ) + dateChanged( int, int, int ) + +
diff --git a/core/pim/todo/todoentryimpl.cpp b/core/pim/todo/todoentryimpl.cpp new file mode 100644 index 0000000..79206de --- a/dev/null +++ b/core/pim/todo/todoentryimpl.cpp @@ -0,0 +1,142 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "todoentryimpl.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +NewTaskDialog::NewTaskDialog( const Task& task, QWidget *parent, + const char *name, bool modal, WFlags fl ) + : NewTaskDialogBase( parent, name, modal, fl ), + todo( task ) +{ + todo.setCategories( task.categories() ); + if ( todo.hasDueDate() ) + date = todo.dueDate(); + else + date = QDate::currentDate(); + + init(); + comboPriority->setCurrentItem( task.priority() - 1 ); + + checkCompleted->setChecked( task.isCompleted() ); + checkDate->setChecked( task.hasDueDate() ); + buttonDate->setText( TimeString::longDateString( date ) ); + + txtTodo->setText( task.description() ); +} + +/* + * Constructs a NewTaskDialog which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +NewTaskDialog::NewTaskDialog( int id, QWidget* parent, const char* name, bool modal, + WFlags fl ) + : NewTaskDialogBase( parent, name, modal, fl ), + date( QDate::currentDate() ) +{ + if ( id != -1 ) { + QArray ids( 1 ); + ids[0] = id; + todo.setCategories( ids ); + } + init(); +} + +void NewTaskDialog::init() +{ + QPopupMenu *m1 = new QPopupMenu( this ); + picker = new DateBookMonth( m1, 0, TRUE ); + m1->insertItem( picker ); + buttonDate->setPopup( m1 ); + comboCategory->setCategories( todo.categories(), "Todo List", tr("Todo List") ); + + connect( picker, SIGNAL( dateClicked( int, int, int ) ), + this, SLOT( dateChanged( int, int, int ) ) ); + + buttonDate->setText( TimeString::longDateString( date ) ); + picker->setDate( date.year(), date.month(), date.day() ); +} + +/* + * Destroys the object and frees any allocated resources + */ +NewTaskDialog::~NewTaskDialog() +{ + // no need to delete child widgets, Qt does it all for us +} +void NewTaskDialog::dateChanged( int y, int m, int d ) +{ + date = QDate( y, m, d ); + buttonDate->setText( TimeString::longDateString( date ) ); +} + +/*! +*/ + +Task NewTaskDialog::todoEntry() +{ + todo.setDueDate( date, checkDate->isChecked() ); + if ( comboCategory->currentCategory() != -1 ) { + todo.setCategories( comboCategory->currentCategories() ); + } + todo.setPriority( comboPriority->currentItem() + 1 ); + todo.setCompleted( checkCompleted->isChecked() ); + + todo.setDescription( txtTodo->text() ); + + return todo; +} + + +/*! + +*/ + +void NewTaskDialog::accept() +{ + QString strText = txtTodo->text(); + if ( !strText || strText == "") { + // hmm... just decline it then, the user obviously didn't care about it + QDialog::reject(); + return; + } + QDialog::accept(); +} diff --git a/core/pim/todo/todoentryimpl.h b/core/pim/todo/todoentryimpl.h new file mode 100644 index 0000000..932d66e --- a/dev/null +++ b/core/pim/todo/todoentryimpl.h @@ -0,0 +1,61 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef NEWTASKDIALOG_H +#define NEWTASKDIALOG_H + +#include "todoentry.h" + +#include + +#include +#include + +class QLabel; +class QTimer; +class DateBookMonth; + +class NewTaskDialog : public NewTaskDialogBase +{ + Q_OBJECT + +public: + NewTaskDialog( const Task &task, QWidget *parent = 0, const char* name = 0, + bool modal = FALSE, WFlags fl = 0 ); + NewTaskDialog( int id, QWidget* parent = 0, const char* name = 0, + bool modal = FALSE, WFlags fl = 0 ); + ~NewTaskDialog(); + + Task todoEntry(); + +protected slots: + void dateChanged( int y, int m, int d ); + +protected: + virtual void accept(); + +private: + void init(); + Task todo; + QDate date; + DateBookMonth *picker; +}; + +#endif // NEWTASKDIALOG_H diff --git a/core/pim/todo/todotable.cpp b/core/pim/todo/todotable.cpp new file mode 100644 index 0000000..77d3389 --- a/dev/null +++ b/core/pim/todo/todotable.cpp @@ -0,0 +1,859 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "todotable.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + + +static bool taskCompare( const Task &task, const QRegExp &r, int category ); + +static QString journalFileName(); + +CheckItem::CheckItem( QTable *t, const QString &key ) + : QTableItem( t, Never, "" ), checked( FALSE ), sortKey( key ) +{ +} + +QString CheckItem::key() const +{ + return sortKey; +} + +void CheckItem::setChecked( bool b ) +{ + checked = b; + table()->updateCell( row(), col() ); +} + +void CheckItem::toggle() +{ + TodoTable *parent = static_cast(table()); + Task newTodo = parent->currentEntry(); + checked = !checked; + newTodo.setCompleted( checked ); + table()->updateCell( row(), col() ); + parent->replaceCurrentEntry( newTodo, true ); +} + +bool CheckItem::isChecked() const +{ + return checked; +} + +static const int BoxSize = 10; + +void CheckItem::paint( QPainter *p, const QColorGroup &cg, const QRect &cr, + bool ) +{ + p->fillRect( 0, 0, cr.width(), cr.height(), cg.brush( QColorGroup::Base ) ); + + int marg = ( cr.width() - BoxSize ) / 2; + int x = 0; + int y = ( cr.height() - BoxSize ) / 2; + p->setPen( QPen( cg.text() ) ); + p->drawRect( x + marg, y, BoxSize, BoxSize ); + p->drawRect( x + marg+1, y+1, BoxSize-2, BoxSize-2 ); + p->setPen( darkGreen ); + x += 1; + y += 1; + if ( checked ) { + QPointArray a( 7*2 ); + int i, xx, yy; + xx = x+1+marg; + yy = y+2; + for ( i=0; i<3; i++ ) { + a.setPoint( 2*i, xx, yy ); + a.setPoint( 2*i+1, xx, yy+2 ); + xx++; yy++; + } + yy -= 2; + for ( i=3; i<7; i++ ) { + a.setPoint( 2*i, xx, yy ); + a.setPoint( 2*i+1, xx, yy+2 ); + xx++; yy--; + } + p->drawLineSegments( a ); + } +} + + +ComboItem::ComboItem( QTable *t, EditType et ) + : QTableItem( t, et, "3" ), cb( 0 ) +{ + setReplaceable( FALSE ); +} + +QWidget *ComboItem::createEditor() const +{ + QString txt = text(); + ( (ComboItem*)this )->cb = new QComboBox( table()->viewport() ); + cb->insertItem( "1" ); + cb->insertItem( "2" ); + cb->insertItem( "3" ); + cb->insertItem( "4" ); + cb->insertItem( "5" ); + cb->setCurrentItem( txt.toInt() - 1 ); + return cb; +} + +void ComboItem::setContentFromEditor( QWidget *w ) +{ + TodoTable *parent = static_cast(table()); + Task newTodo = parent->currentEntry(); + + if ( w->inherits( "QComboBox" ) ) + setText( ( (QComboBox*)w )->currentText() ); + else + QTableItem::setContentFromEditor( w ); + newTodo.setPriority( text().toInt() ); + parent->replaceCurrentEntry( newTodo, true ); +} + +void ComboItem::setText( const QString &s ) +{ + if ( cb ) + cb->setCurrentItem( s.toInt() - 1 ); + QTableItem::setText( s ); +} + +QString ComboItem::text() const +{ + if ( cb ) + return cb->currentText(); + return QTableItem::text(); +} + + + +TodoTable::TodoTable( QWidget *parent, const char *name ) +// #ifdef QT_QTABLE_NOHEADER_CONSTRUCTOR +// : QTable( 0, 3, parent, name, TRUE ), +// #else + : QTable( 0, 3, parent, name ), +// #endif + showComp( true ), + enablePainting( true ), + mCat( 0 ), + currFindRow( -2 ) +{ + mCat.load( categoryFileName() ); + setSorting( TRUE ); + setSelectionMode( NoSelection ); + setColumnStretchable( 2, TRUE ); + setColumnWidth( 0, 20 ); + setColumnWidth( 1, 35 ); + setLeftMargin( 0 ); + verticalHeader()->hide(); + horizontalHeader()->setLabel( 0, tr( "C." ) ); + horizontalHeader()->setLabel( 1, tr( "Prior." ) ); + horizontalHeader()->setLabel( 2, tr( "Description" ) ); + connect( this, SIGNAL( clicked( int, int, int, const QPoint & ) ), + this, SLOT( slotClicked( int, int, int, const QPoint & ) ) ); + connect( this, SIGNAL( pressed( int, int, int, const QPoint & ) ), + this, SLOT( slotPressed( int, int, int, const QPoint & ) ) ); + connect( this, SIGNAL( valueChanged( int, int ) ), + this, SLOT( slotCheckPriority( int, int ) ) ); + connect( this, SIGNAL( currentChanged( int, int ) ), + this, SLOT( slotCurrentChanged( int, int ) ) ); + + menuTimer = new QTimer( this ); + connect( menuTimer, SIGNAL(timeout()), this, SLOT(slotShowMenu()) ); +} + +void TodoTable::addEntry( const Task &todo ) +{ + int row = numRows(); + setNumRows( row + 1 ); + updateJournal( todo, ACTION_ADD ); + insertIntoTable( new Task(todo), row ); + setCurrentCell(row, currentColumn()); + updateVisible(); +} + +void TodoTable::slotClicked( int row, int col, int, const QPoint &pos ) +{ + if ( !cellGeometry( row, col ).contains(pos) ) + return; + // let's switch on the column number... + switch ( col ) + { + case 0: { + CheckItem *i = static_cast(item( row, col )); + if ( i ) { + int x = pos.x() - columnPos( col ); + int y = pos.y() - rowPos( row ); + int w = columnWidth( col ); + int h = rowHeight( row ); + if ( i && x >= ( w - BoxSize ) / 2 && x <= ( w - BoxSize ) / 2 + BoxSize && + y >= ( h - BoxSize ) / 2 && y <= ( h - BoxSize ) / 2 + BoxSize ) { + i->toggle(); + } + emit signalDoneChanged( i->isChecked() ); + } + } + break; + case 1: + break; + case 2: + // may as well edit it... + menuTimer->stop(); +// emit signalEdit(); + break; + } +} + +void TodoTable::slotPressed( int row, int col, int, const QPoint &pos ) +{ + if ( col == 2 && cellGeometry( row, col ).contains(pos) ) + menuTimer->start( 750, TRUE ); +} + +void TodoTable::slotShowMenu() +{ + emit signalShowMenu( QCursor::pos() ); +} + +void TodoTable::slotCurrentChanged( int, int ) +{ + menuTimer->stop(); +} + +void TodoTable::internalAddEntries( QList &list ) +{ + setNumRows( list.count() ); + int row = 0; + Task *it; + for ( it = list.first(); it; it = list.next() ) + insertIntoTable( it, row++ ); +} + + +Task TodoTable::currentEntry() const +{ + QTableItem *i = item( currentRow(), 0 ); + if ( !i || rowHeight( currentRow() ) <= 0 ) + return Task(); + Task *todo = todoList[(CheckItem*)i]; + todo->setCompleted( ( (CheckItem*)item( currentRow(), 0 ) )->isChecked() ); + todo->setPriority( ( (ComboItem*)item( currentRow(), 1 ) )->text().toInt() ); + return *todo; +} + +void TodoTable::replaceCurrentEntry( const Task &todo, bool fromTableItem ) +{ + int row = currentRow(); + updateJournal( todo, ACTION_REPLACE, row ); + + if ( !fromTableItem ) { + journalFreeReplaceEntry( todo, row ); + updateVisible(); + } +} + +void TodoTable::removeCurrentEntry() +{ + Task *oldTodo; + int row = currentRow(); + CheckItem *chk; + + chk = static_cast(item(row, 0 )); + if ( !chk ) + return; + oldTodo = todoList[chk]; + todoList.remove( chk ); + oldTodo->setCompleted( chk->isChecked() ); + oldTodo->setPriority( static_cast(item(row, 1))->text().toInt() ); + realignTable( row ); + updateVisible(); + updateJournal( *oldTodo, ACTION_REMOVE, row ); + delete oldTodo; +} + + +bool TodoTable::save( const QString &fn ) +{ + QString strNewFile = fn + ".new"; + QFile f( strNewFile ); + if ( !f.open( IO_WriteOnly|IO_Raw ) ) + return false; + + QString buf("\n\n"); + QCString str; + int total_written; + + for ( QMap::Iterator it = todoList.begin(); + it != todoList.end(); ++it ) { + if ( !item( it.key()->row(), 0 ) ) + continue; + Task *todo = *it; + // sync item with table + todo->setCompleted( ((CheckItem*)item(it.key()->row(), 0))->isChecked() ); + todo->setPriority( ((ComboItem*)item( it.key()->row(), 1))->text().toInt() ); + buf += "save( buf ); + buf += " />\n"; + str = buf.utf8(); + total_written = f.writeBlock( str.data(), str.length() ); + if ( total_written != int(str.length()) ) { + f.close(); + QFile::remove( strNewFile ); + return false; + } + buf = ""; + } + + buf += "\n"; + str = buf.utf8(); + total_written = f.writeBlock( str.data(), str.length() ); + if ( total_written != int(str.length()) ) { + f.close(); + QFile::remove( strNewFile ); + return false; + } + f.close(); + + // now do the rename + if ( ::rename( strNewFile, fn ) < 0 ) + qWarning( "problem renaming file %s to %s errno %d", + strNewFile.latin1(), fn.latin1(), errno ); + + // remove the journal + QFile::remove( journalFileName() ); + return true; +} + +void TodoTable::load( const QString &fn ) +{ + loadFile( fn, false ); + if ( QFile::exists(journalFileName()) ) { + loadFile( journalFileName(), true ); + save( fn ); + } +// QTable::sortColumn(2,TRUE,TRUE); +// QTable::sortColumn(1,TRUE,TRUE); + QTable::sortColumn(0,TRUE,TRUE); + setCurrentCell( 0, 2 ); +} + +void TodoTable::updateVisible() +{ + if ( !isUpdatesEnabled() ) + return; + +// qDebug("--> updateVisible!"); + + int visible = 0; + int id = mCat.id( "Todo List", showCat ); + for ( int row = 0; row < numRows(); row++ ) { + CheckItem *ci = (CheckItem *)item( row, 0 ); + Task *t = todoList[ci]; + QArray vlCats = t->categories(); + bool hide = false; + if ( !showComp && ci->isChecked() ) + hide = true; + if ( !showCat.isEmpty() ) { + if ( showCat == tr( "Unfiled" ) ) { + if ( vlCats.count() > 0 ) + hide = true; + } else { + // do some comparing, we have to reverse our idea here... + if ( !hide ) { + hide = true; + for ( uint it = 0; it < vlCats.count(); ++it ) { + if ( vlCats[it] == id ) { + hide = false; + break; + } + } + } + } + } + if ( hide ) { + if ( currentRow() == row ) + setCurrentCell( -1, 0 ); + if ( rowHeight( row ) > 0 ) + hideRow( row ); + } else { + if ( rowHeight( row ) == 0 ) { + showRow( row ); + adjustRow( row ); + } + visible++; + } + } + if ( !visible ) + setCurrentCell( -1, 0 ); +} + +void TodoTable::viewportPaintEvent( QPaintEvent *pe ) +{ + if ( enablePainting ) + QTable::viewportPaintEvent( pe ); +} + +void TodoTable::setPaintingEnabled( bool e ) +{ + if ( e != enablePainting ) { + if ( !enablePainting ) { + enablePainting = true; + rowHeightChanged( 0 ); + viewport()->update(); + } else { + enablePainting = false; + } + } +} + +void TodoTable::clear() +{ + for ( QMap::Iterator it = todoList.begin(); + it != todoList.end(); ++it ) { + Task *todo = *it; + delete todo; + } + todoList.clear(); + for ( int r = 0; r < numRows(); ++r ) { + for ( int c = 0; c < numCols(); ++c ) { + if ( cellWidget( r, c ) ) + clearCellWidget( r, c ); + clearCell( r, c ); + } + } + setNumRows( 0 ); +} + +void TodoTable::sortColumn( int col, bool /*ascending*/, bool /*wholeRows*/ ) +{ + // The default for wholeRows is false, however + // for this todo table we want to exchange complete + // rows when sorting. Also, we always want ascending, since + // the values have a logical order. + QTable::sortColumn( col, TRUE, TRUE ); + updateVisible(); +} + +void TodoTable::slotCheckPriority(int row, int col ) +{ + // kludgey work around to make forward along the updated priority... + if ( col == 1 ) { + // let everyone know!! + ComboItem* i = static_cast( item( row, col ) ); + emit signalPriorityChanged( i->text().toInt() ); + } +} + + +void TodoTable::updateJournal( const Task &todo, journal_action action, int row ) +{ + QFile f( journalFileName() ); + if ( !f.open(IO_WriteOnly|IO_Append) ) + return; + QString buf; + QCString str; + buf = " dict( 31 ); + QList list; + dict.setAutoDelete( TRUE ); + dict.insert( "Completed", new int(FCompleted) ); + dict.insert( "HasDate", new int(FHasDate) ); + dict.insert( "Priority", new int(FPriority) ); + dict.insert( "Categories", new int(FCategories) ); + dict.insert( "Description", new int(FDescription) ); + dict.insert( "DateYear", new int(FDateYear) ); + dict.insert( "DateMonth", new int(FDateMonth) ); + dict.insert( "DateDay", new int(FDateDay) ); + dict.insert( "Uid", new int(FUid) ); + dict.insert( "Action", new int(FAction) ); + dict.insert( "Row", new int(FRow) ); + + QByteArray ba = f.readAll(); + f.close(); + char* dt = ba.data(); + int len = ba.size(); + bool hasDueDate = FALSE; + + action = ACTION_ADD; + int i = 0; + char *point; + while ( ( point = strstr( dt+i, "= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) + break; + // we have another attribute, read it. + int j = i; + while ( j < len && dt[j] != '=' ) + ++j; + char *attr = dt+i; + dt[j] = '\0'; + i = ++j; // skip = + while ( i < len && dt[i] != '"' ) + ++i; + j = ++i; + bool haveUtf = FALSE; + bool haveEnt = FALSE; + while ( j < len && dt[j] != '"' ) { + if ( ((unsigned char)dt[j]) > 0x7f ) + haveUtf = TRUE; + if ( dt[j] == '&' ) + haveEnt = TRUE; + ++j; + } + if ( i == j ) { + // empty value + i = j + 1; + continue; + } + QCString value( dt+i, j-i+1 ); + i = j + 1; + int *lookup = dict[ attr ]; + if ( !lookup ) { + todo->setCustomField(attr, value); + continue; + } + switch( *lookup ) { + case FCompleted: + todo->setCompleted( value.toInt() ); + break; + case FHasDate: + // leave... + hasDueDate = value.toInt(); + break; + case FPriority: + todo->setPriority( value.toInt() ); + break; + case FCategories: { + //QString str = Qtopia::plainString( value ); + todo->setCategories( Qtopia::Record::idsFromString( value ) ); + break; + } + case FDescription: + { + QString str = (haveUtf ? QString::fromUtf8( value ) + : QString::fromLatin1( value ) ); + if ( haveEnt ) + str = Qtopia::plainString( str ); + todo->setDescription( str ); + break; + } + case FDateYear: + dtY = value.toInt(); + break; + case FDateMonth: + dtM = value.toInt(); + break; + case FDateDay: + dtD = value.toInt(); + break; + case FUid: + todo->setUid( value.toInt() ); + break; + case FAction: + action = value.toInt(); + break; + case FRow: + row = value.toInt(); + break; + default: + qDebug( "huh??? missing enum? -- attr.: %s", attr ); + break; + } + } + + if ( dtY != 0 && dtM != 0 && dtD != 0 ) + todo->setDueDate( QDate( dtY, dtM, dtD), hasDueDate ); + else + todo->setHasDueDate( hasDueDate ); + +// if ( categoryList.find( todo.category() ) == categoryList.end() ) +// categoryList.append( todo.category() ); + + + // sadly we can't delay adding of items from the journal to get + // the proper effect, but then, the journal should _never_ be + // that huge + + switch( action ) { + case ACTION_ADD: + if ( fromJournal ) { + int myrows = numRows(); + setNumRows( myrows + 1 ); + insertIntoTable( todo, myrows ); + delete todo; + } else + list.append( todo ); + break; + case ACTION_REMOVE: + journalFreeRemoveEntry( row ); + break; + case ACTION_REPLACE: + journalFreeReplaceEntry( *todo, row ); + delete todo; + break; + default: + break; + } + } +// qDebug("parsing done=%d", t.elapsed() ); + if ( list.count() > 0 ) { + internalAddEntries( list ); + list.clear(); + } +// qDebug("loading done: t=%d", t.elapsed() ); +} + +void TodoTable::journalFreeReplaceEntry( const Task &todo, int row ) +{ + QString strTodo; + strTodo = todo.description().left(40).simplifyWhiteSpace(); + if ( row == -1 ) { + QMapIterator it; + for ( it = todoList.begin(); it != todoList.end(); ++it ) { + if ( *(*it) == todo ) { + row = it.key()->row(); + it.key()->setChecked( todo.isCompleted() ); + static_cast(item(row, 1))->setText( QString::number(todo.priority()) ); + item( row, 2 )->setText( strTodo ); + *(*it) = todo; + } + } + } else { + Task *t = todoList[static_cast(item(row, 0))]; + todoList.remove( static_cast(item(row, 0)) ); + delete t; + static_cast(item(row, 0))->setChecked( todo.isCompleted() ); + static_cast(item(row, 1))->setText( QString::number(todo.priority()) ); + item( row, 2 )->setText( strTodo ); + todoList.insert( static_cast(item(row,0)), new Task(todo) ); + } +} + +void TodoTable::journalFreeRemoveEntry( int row ) +{ + CheckItem *chk; + chk = static_cast(item(row, 0 )); + if ( !chk ) + return; + todoList.remove( chk ); + + realignTable( row ); +} + +void TodoTable::keyPressEvent( QKeyEvent *e ) +{ + if ( e->key() == Key_Space || e->key() == Key_Return ) { + switch ( currentColumn() ) { + case 0: { + CheckItem *i = static_cast(item(currentRow(), + currentColumn())); + if ( i ) + i->toggle(); + break; + } + case 1: + break; + case 2: + emit signalEdit(); + default: + break; + } + } else { + QTable::keyPressEvent( e ); + } +} + +QStringList TodoTable::categories() +{ + // This is called seldom, so calling a load in here + // should be fine. + mCat.load( categoryFileName() ); + QStringList categoryList = mCat.labels( "Todo List" ); + return categoryList; +} + +void TodoTable::slotDoFind( const QString &findString, bool caseSensitive, + bool backwards, int category ) +{ + // we have to iterate through the table, this gives the illusion that + // sorting is actually being used. + if ( currFindRow < -1 ) + currFindRow = currentRow() - 1; + clearSelection( TRUE ); + int rows, + row; + CheckItem *chk; + QRegExp r( findString ); + + r.setCaseSensitive( caseSensitive ); + rows = numRows(); + static bool wrapAround = true; + + if ( !backwards ) { + for ( row = currFindRow + 1; row < rows; row++ ) { + chk = static_cast( item(row, 0) ); + if ( taskCompare(*(todoList[chk]), r, category) ) + break; + } + } else { + for ( row = currFindRow - 1; row > -1; row-- ) { + chk = static_cast( item(row, 0) ); + if ( taskCompare(*(todoList[chk]), r, category) ) + break; + } + } + if ( row >= rows || row < 0 ) { + if ( row < 0 ) + currFindRow = rows; + else + currFindRow = -1; + if ( wrapAround ) + emit signalWrapAround(); + else + emit signalNotFound(); + wrapAround = !wrapAround; + } else { + currFindRow = row; + QTableSelection foundSelection; + foundSelection.init( currFindRow, 0 ); + foundSelection.expandTo( currFindRow, numCols() - 1 ); + addSelection( foundSelection ); + setCurrentCell( currFindRow, numCols() - 1 ); + // we should always be able to wrap around and find this again, + // so don't give confusing not found message... + wrapAround = true; + } +} + +int TodoTable::showCategoryId() const +{ + int id; + id = -1; + // if allcategories are selected, you get unfiled... + if ( showCat != tr( "Unfiled" ) && showCat != tr( "All" ) ) + id = mCat.id( "Todo List", showCat ); + return id; +} + +static bool taskCompare( const Task &task, const QRegExp &r, int category ) +{ + bool returnMe; + QArray cats; + cats = task.categories(); + + returnMe = false; + if ( (category == -1 && cats.count() == 0) || category == -2 ) + returnMe = task.match( r ); + else { + int i; + for ( i = 0; i < int(cats.count()); i++ ) { + if ( cats[i] == category ) { + returnMe = task.match( r ); + break; + } + } + } + return returnMe; +} + +static QString journalFileName() +{ + QString str; + str = getenv( "HOME" ); + str += "/.todojournal"; + return str; +} + +// int TodoTable::rowHeight( int ) const +// { +// return 18; +// } + +// int TodoTable::rowPos( int row ) const +// { +// return 18*row; +// } + +// int TodoTable::rowAt( int pos ) const +// { +// return QMIN( pos/18, numRows()-1 ); +// } diff --git a/core/pim/todo/todotable.h b/core/pim/todo/todotable.h new file mode 100644 index 0000000..4f3a064 --- a/dev/null +++ b/core/pim/todo/todotable.h @@ -0,0 +1,207 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef TODOTABLE_H +#define TODOTABLE_H + +#include +#include +#include + +#include +#include +#include + +class Node; +class QComboBox; +class QTimer; + +class CheckItem : public QTableItem +{ +public: + CheckItem( QTable *t, const QString &sortkey ); + + void setChecked( bool b ); + void toggle(); + bool isChecked() const; + void setKey( const QString &key ) { sortKey = key; } + QString key() const; + + void paint( QPainter *p, const QColorGroup &cg, const QRect &cr, bool selected ); + +private: + bool checked; + QString sortKey; +}; + +class ComboItem : public QTableItem +{ +public: + ComboItem( QTable *t, EditType et ); + QWidget *createEditor() const; + void setContentFromEditor( QWidget *w ); + void setText( const QString &s ); + int alignment() const { return Qt::AlignCenter; } + + QString text() const; + +private: + QGuardedPtr cb; + +}; + +class TodoTextItem : public QTableItem +{ +public: + TodoTextItem( QTable *t, const QString & str ) + :QTableItem( t, QTableItem::Never, str ) {} + + QString key () const { return Qtopia::buildSortKey( text() ); } +}; + + + +enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE }; + +class TodoTable : public QTable +{ + Q_OBJECT + +public: + TodoTable( QWidget *parent = 0, const char * name = 0 ); + void addEntry( const Task &todo ); + void clearFindRow() { currFindRow = -2; } + + Task currentEntry() const; + void replaceCurrentEntry( const Task &todo, bool fromTableItem = false ); + + QStringList categories(); + + void setShowCompleted( bool sc ) { showComp = sc; updateVisible(); } + bool showCompleted() const { return showComp; } + + void setShowCategory( const QString &c ) { showCat = c; updateVisible(); } + const QString &showCategory() const { return showCat; } + int showCategoryId() const; + + bool save( const QString &fn ); + void load( const QString &fn ); + void clear(); + void removeCurrentEntry(); + + void setPaintingEnabled( bool e ); + + virtual void sortColumn( int col, bool ascending, bool /*wholeRows*/ ); + +// int rowHeight( int ) const; +// int rowPos( int row ) const; +// virtual int rowAt( int pos ) const; + +signals: + void signalEdit(); + void signalDoneChanged( bool b ); + void signalPriorityChanged( int i ); + void signalShowMenu( const QPoint & ); + void signalNotFound(); + void signalWrapAround(); + +protected: + void keyPressEvent( QKeyEvent *e ); + +private: + void updateVisible(); + void viewportPaintEvent( QPaintEvent * ); + void internalAddEntries( QList &list); + inline void insertIntoTable( Task *todo, int row ); + void updateJournal( const Task &todo, journal_action action, int row = -1); + void mergeJournal(); + void journalFreeReplaceEntry( const Task &todo, int row ); + void journalFreeRemoveEntry( int row ); + inline void realignTable( int row ); + void loadFile( const QString &strFile, bool fromJournal = false ); + +private slots: + void slotClicked( int row, int col, int button, const QPoint &pos ); + void slotPressed( int row, int col, int button, const QPoint &pos ); + void slotCheckPriority(int row, int col ); + void slotCurrentChanged(int row, int col ); + void slotDoFind( const QString &findString, bool caseSensetive, + bool backwards, int category ); + void slotShowMenu(); + void rowHeightChanged( int row ); + +private: + friend class TodoWindow; + + QMap todoList; + QStringList categoryList; + bool showComp; + QString showCat; + QTimer *menuTimer; + bool enablePainting; + Categories mCat; + int currFindRow; +}; + + +inline void TodoTable::insertIntoTable( Task *todo, int row ) +{ + QString sortKey = (char) ((todo->isCompleted() ? 'a' : 'A') + + todo->priority() ) + + Qtopia::buildSortKey( todo->description() ); + CheckItem *chk = new CheckItem( this, sortKey ); + chk->setChecked( todo->isCompleted() ); + ComboItem *cmb = new ComboItem( this, QTableItem::WhenCurrent ); + cmb->setText( QString::number( todo->priority() ) ); + QTableItem *ti = new TodoTextItem( this, todo->description().left(40).simplifyWhiteSpace() ); + ti->setReplaceable( false ); + + setItem( row, 0, chk ); + setItem( row, 1, cmb ); + setItem( row, 2, ti ); + + todoList.insert( chk, todo ); +} + +inline void TodoTable::realignTable( int row ) +{ + QTableItem *ti1, + *ti2, + *ti3; + int totalRows = numRows(); + for ( int curr = row; curr < totalRows - 1; curr++ ) { + // this is bad, we must take the item out and then + // set it. In the end, it behaves no worse (time wise) + // then the old way of saving the entries to file, clearing + // the table re-reading in the file and resetting the table + ti1 = item( curr + 1, 0 ); + ti2 = item( curr + 1, 1 ); + ti3 = item( curr + 1, 2 ); + takeItem( ti1 ); + takeItem( ti2 ); + takeItem( ti3 ); + setItem( curr, 0, ti1 ); + setItem( curr, 1, ti2 ); + setItem( curr, 2, ti3 ); + } + setNumRows( totalRows - 1 ); +} + +#endif diff --git a/core/settings/citytime/.cvsignore b/core/settings/citytime/.cvsignore new file mode 100644 index 0000000..d316ac9 --- a/dev/null +++ b/core/settings/citytime/.cvsignore @@ -0,0 +1,5 @@ +moc_* +*.moc +Makefile +citytimebase.cpp +citytimebase.h diff --git a/core/settings/citytime/Makefile.in b/core/settings/citytime/Makefile.in new file mode 100644 index 0000000..b058021 --- a/dev/null +++ b/core/settings/citytime/Makefile.in @@ -0,0 +1,184 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = $(QPEDIR)/bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = citytime +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = citytime.h \ + zonemap.h \ + sun.h \ + stylusnormalizer.h +SOURCES = citytime.cpp \ + zonemap.cpp \ + main.cpp \ + sun.c \ + stylusnormalizer.cpp +OBJECTS = citytime.o \ + zonemap.o \ + main.o \ + sun.o \ + stylusnormalizer.o \ + citytimebase.o +INTERFACES = citytimebase.ui +UICDECLS = citytimebase.h +UICIMPLS = citytimebase.cpp +SRCMOC = moc_citytime.cpp \ + moc_zonemap.cpp \ + moc_stylusnormalizer.cpp \ + moc_citytimebase.cpp +OBJMOC = moc_citytime.o \ + moc_zonemap.o \ + moc_stylusnormalizer.o \ + moc_citytimebase.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake citytime.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +citytime.o: citytime.cpp \ + zonemap.h \ + stylusnormalizer.h \ + citytime.h \ + citytimebase.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/timestring.h \ + $(QPEDIR)/include/qpe/tzselect.h \ + $(QPEDIR)/include/qpe/qcopenvelope_qws.h + +zonemap.o: zonemap.cpp \ + sun.h \ + zonemap.h \ + stylusnormalizer.h \ + $(QPEDIR)/include/qpe/resource.h \ + $(QPEDIR)/include/qpe/timestring.h \ + $(QPEDIR)/include/qpe/qpeapplication.h + +main.o: main.cpp \ + citytime.h \ + citytimebase.h \ + $(QPEDIR)/include/qpe/qpeapplication.h + +sun.o: sun.c \ + sun.h \ + $(QPEDIR)/include/qpe/qmath.h + +stylusnormalizer.o: stylusnormalizer.cpp \ + stylusnormalizer.h + +citytimebase.h: citytimebase.ui + $(UIC) citytimebase.ui -o $(INTERFACE_DECL_PATH)/citytimebase.h + +citytimebase.cpp: citytimebase.ui + $(UIC) citytimebase.ui -i citytimebase.h -o citytimebase.cpp + +citytimebase.o: citytimebase.cpp \ + citytimebase.h \ + citytimebase.ui + +moc_citytime.o: moc_citytime.cpp \ + citytime.h \ + citytimebase.h + +moc_zonemap.o: moc_zonemap.cpp \ + zonemap.h \ + stylusnormalizer.h + +moc_stylusnormalizer.o: moc_stylusnormalizer.cpp \ + stylusnormalizer.h + +moc_citytimebase.o: moc_citytimebase.cpp \ + citytimebase.h + +moc_citytime.cpp: citytime.h + $(MOC) citytime.h -o moc_citytime.cpp + +moc_zonemap.cpp: zonemap.h + $(MOC) zonemap.h -o moc_zonemap.cpp + +moc_stylusnormalizer.cpp: stylusnormalizer.h + $(MOC) stylusnormalizer.h -o moc_stylusnormalizer.cpp + +moc_citytimebase.cpp: citytimebase.h + $(MOC) citytimebase.h -o moc_citytimebase.cpp + + diff --git a/core/settings/citytime/citytime.cpp b/core/settings/citytime/citytime.cpp new file mode 100644 index 0000000..b2f9f14 --- a/dev/null +++ b/core/settings/citytime/citytime.cpp @@ -0,0 +1,272 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "zonemap.h" +#include "citytime.h" + +#include +#include +#include +#include +#if ( defined Q_WS_QWS || defined(_WS_QWS_) ) && !defined(QT_NO_COP) +#include +#endif + + +#include +#include +#include +#include +#include +#include +#include + +#include + +CityTime::CityTime( QWidget *parent, const char* name, + WFlags fl ) + : CityTimeBase( parent, name, fl ), + strRealTz(0), + bAdded(false) +{ + Config config( "qpe" ); + bWhichClock = config.readBoolEntry( "AMPM", TRUE ); + frmMap->changeClock( bWhichClock ); + + char *pEnv; + pEnv = NULL; + pEnv = getenv("TZ"); + if ( pEnv ) + strRealTz = pEnv; + pEnv = NULL; + pEnv = getenv("HOME"); + if ( pEnv ) + strHome = pEnv; + // append the labels to their respective lists... + listCities.setAutoDelete( true ); + listTimes.setAutoDelete( true ); + + listCities.append( cmdCity1 ); + listCities.append( cmdCity2 ); + listCities.append( cmdCity3 ); + + listTimes.append( lblCTime1 ); + listTimes.append( lblCTime2 ); + listTimes.append( lblCTime3 ); + + + // kludgy way of getting the screen size so we don't have to depend + // on a resize event... + QWidget *d = QApplication::desktop(); + if ( d->width() < d->height() ) { + // append for that 4 down look + + listCities.append( cmdCity4 ); + listCities.append( cmdCity5 ); + listCities.append( cmdCity6 ); + listTimes.append( lblCTime4 ); + listTimes.append( lblCTime5 ); + listTimes.append( lblCTime6 ); + lblCTime7->hide(); + lblCTime8->hide(); + lblCTime9->hide(); + cmdCity7->hide(); + cmdCity8->hide(); + cmdCity9->hide(); + } else { + listCities.append( cmdCity7 ); + listCities.append( cmdCity8 ); + listCities.append( cmdCity9 ); + listTimes.append( lblCTime7 ); + listTimes.append( lblCTime8 ); + listTimes.append( lblCTime9 ); + lblCTime4->hide(); + lblCTime5->hide(); + lblCTime6->hide(); + cmdCity4->hide(); + cmdCity5->hide(); + cmdCity6->hide(); + } + bAdded = true; + readInTimes(); + changed = FALSE; + QObject::connect( qApp, SIGNAL( clockChanged(bool) ), + this, SLOT( changeClock(bool) ) ); + // now start the timer so we can update the time quickly every second + timerEvent( 0 ); +} + +CityTime::~CityTime() +{ + if ( changed ) { + Config cfg("CityTime"); + cfg.setGroup("TimeZones"); + QListIterator itCity( listCities ); + int i; + bool realTzWritten = FALSE; + for ( i = 0, itCity.toFirst(); i < CITIES; i++, ++itCity ) { + if ( !strCityTz[i].isNull() ) { + cfg.writeEntry("Zone"+QString::number(i), strCityTz[i]); + cfg.writeEntry("ZoneName"+QString::number(i), itCity.current()->text()); + if ( strCityTz[i] == strRealTz ) + realTzWritten = TRUE; + } + } + if ( realTzWritten ) { + cfg.removeEntry("Zone"+QString::number(CITIES)); + cfg.removeEntry("ZoneName"+QString::number(CITIES)); + } else { + cfg.writeEntry("Zone"+QString::number(CITIES), strRealTz); + if ( nameRealTz.isEmpty() ) { + int i = strRealTz.find( '/' ); + nameRealTz = strRealTz.mid( i+1 ); + } + cfg.writeEntry("ZoneName"+QString::number(CITIES), nameRealTz); + } + QCopEnvelope ( "QPE/System", "timeZoneListChange()" ); + + changed = FALSE; + } + // restore the timezone, just in case we messed with it and + // are destroyed at an inoppurtune moment + if ( !strRealTz.isNull() ) { + // this should be checked, but there is not much that can done at this + //point if it fails + setenv( "TZ", strRealTz, true ); + } +} + +void CityTime::timerEvent( QTimerEvent *e ) +{ + if ( e ) + killTimer( timerId ); + // change the time again!! + showTime(); + int ms = 1000 - QTime::currentTime().msec(); + timerId = startTimer( ms ); +} + +void CityTime::mousePressEvent( QMouseEvent * ) +{ + // DEBUG enable this to get a look at the zone information DEBUG +// frmMap->showZones(); +} + +void CityTime::showTime( void ) +{ + int i; + QListIterator itTime(listTimes); + + // traverse the list... + for ( i = 0, itTime.toFirst(); i < CITIES; i++, ++itTime) { + if ( !strCityTz[i].isNull() ) { + if ( setenv( "TZ", strCityTz[i], true ) == 0 ) { + itTime.current()->setText( TimeString::shortTime(bWhichClock) ); + } else { + QMessageBox::critical( this, tr( "Time Changing" ), + tr( "There was a problem setting timezone %1" ) + .arg( QString::number( i + 1 ) ) ); + } + } + } + // done playing around... put it all back + unsetenv( "TZ" ); + if ( !strRealTz.isNull() ) { + if ( setenv( "TZ", strRealTz, true ) != 0 ) { + QMessageBox::critical( this, tr( "Restore Time Zone" ), + tr( "There was a problem setting your timezone." + "Your time may be wrong now..." ) ); + } + } +} + +void CityTime::beginNewTz() +{ + frmMap->setFocus(); +} + +void CityTime::slotNewTz( const QString & strNewCountry, + const QString & strNewCity ) +{ + // determine what to do based on what putton is pressed... + QListIterator itCity(listCities); + int i; + // go through the list and make adjustments based on which button is on + for ( i = 0, itCity.toFirst(); itCity.current(), i < CITIES; i++, ++itCity ) { + QToolButton *cmdTmp = itCity.current(); + if ( cmdTmp->isOn() ) { + strCityTz[i] = strNewCountry + strNewCity; + QString s = strNewCity; + cmdTmp->setText( s.replace( QRegExp("_"), " " ) ); + cmdTmp->toggle(); + // we can actually break, since there is only one button + // that is ever pressed! + changed = TRUE; + break; + } + } + showTime(); +} + +void CityTime::readInTimes( void ) +{ + Config cfg("CityTime"); + cfg.setGroup("TimeZones"); + QListIterator itCity( listCities ); + int i=0; + nameRealTz = QString::null; + QString zn; + for ( ; i < CITIES ; i++ ) { + zn = cfg.readEntry("Zone"+QString::number(i), QString::null); + if ( zn.isNull() ) + break; + QString nm = cfg.readEntry("ZoneName"+QString::number(i)); + strCityTz[i] = zn; + itCity.current()->setText(nm); + if ( zn == strRealTz ) + nameRealTz = nm; + ++itCity; + } + if ( i == 0 ) { + // write in our own in a shameless self promotion and some humor + QStringList list = timezoneDefaults(); + int i; + QStringList::Iterator it = list.begin(); + for ( i = 0, itCity.toFirst(); i < CITIES && itCity.current(); + i++, ++itCity ) { + strCityTz[i] = *it++; + itCity.current()->setText( *it++ ); + } + } + if ( nameRealTz.isEmpty() ) { + //remember the current time zone even if we don't have room + //to show it. + zn = cfg.readEntry("Zone"+QString::number(CITIES), QString::null); + if ( zn == strRealTz ) + nameRealTz = cfg.readEntry("ZoneName"+QString::number(CITIES)); + i++; + } +} + +void CityTime::changeClock( bool newClock ) +{ + bWhichClock = newClock; + showTime(); +} diff --git a/core/settings/citytime/citytime.h b/core/settings/citytime/citytime.h new file mode 100644 index 0000000..5a2c4d8 --- a/dev/null +++ b/core/settings/citytime/citytime.h @@ -0,0 +1,66 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef TIMEWIDGETIMPL_H +#define TIMEWIDGETIMPL_H + +#include +#include + +#include "citytimebase.h" + +const int CITIES = 6; // the number of cities... + +class ZoneMap; + +class CityTime : public CityTimeBase +{ + Q_OBJECT +public: + CityTime(QWidget* parent = 0, const char *name = 0, WFlags fl = 0); + ~CityTime(); + +public slots: + void beginNewTz(); + void slotNewTz( const QString& strNewCountry, const QString& strNewCity ); + void changeClock( bool newClock ); + +protected: + void timerEvent( QTimerEvent* ); + void mousePressEvent( QMouseEvent* event ); + +private: + void showTime( void ); // get and show the time for various places... + void readInTimes( void ); // a method to get information from the config + QString strRealTz; // save the TZ var + QString nameRealTz; // and what it is called + QString strHome; // the home variable... + bool bAdded; // a flag to indicate things have been added... + bool bWhichClock; + int timerId; + + // a spot to hold the time zone for each city + QString strCityTz[CITIES]; + QList listCities; + QList listTimes; + bool changed; +}; + +#endif diff --git a/core/settings/citytime/citytime.pro b/core/settings/citytime/citytime.pro new file mode 100644 index 0000000..d988b48 --- a/dev/null +++ b/core/settings/citytime/citytime.pro @@ -0,0 +1,13 @@ +# $Id$ +CONFIG += qt warn_on release +TEMPLATE = app +DESTDIR = $(QPEDIR)/bin +INTERFACES = citytimebase.ui +HEADERS = citytime.h zonemap.h sun.h stylusnormalizer.h +SOURCES = citytime.cpp zonemap.cpp main.cpp sun.c stylusnormalizer.cpp +TARGET = citytime +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe + +TRANSLATIONS = ../i18n/de/citytime.ts diff --git a/core/settings/citytime/citytimebase.ui b/core/settings/citytime/citytimebase.ui new file mode 100644 index 0000000..4665097 --- a/dev/null +++ b/core/settings/citytime/citytimebase.ui @@ -0,0 +1,1199 @@ + +CityTimeBase +********************************************************************* +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +** $Id$ +** +********************************************************************* +Trenton Schulz + + QWidget + + name + CityTimeBase + + + geometry + + 0 + 0 + 289 + 359 + + + + caption + City Time + + + layoutMargin + + + layoutSpacing + + + + margin + 0 + + + spacing + 3 + + + ZoneMap + + name + frmMap + + + sizePolicy + + 7 + 7 + + + + + QLayoutWidget + + name + Layout2 + + + layoutMargin + + + layoutSpacing + + + + margin + 4 + + + spacing + 3 + + + QToolButton + + name + cmdCity7 + + + sizePolicy + + 5 + 1 + + + + font + + 1 + + + + focusPolicy + TabFocus + + + text + <location 4> + + + toggleButton + true + + + toggleButton + true + + + + QLabel + + name + lblCTime9 + + + sizePolicy + + 5 + 1 + + + + font + + 10 + + + + text + <CITY 6 TIME> + + + alignment + AlignVCenter|AlignRight + + + hAlign + + + + QToolButton + + name + cmdCity8 + + + sizePolicy + + 5 + 1 + + + + font + + 1 + + + + focusPolicy + TabFocus + + + text + <location 5> + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdCity2 + + + font + + 1 + + + + focusPolicy + TabFocus + + + text + <location 2> + + + toggleButton + true + + + toggleButton + true + + + + QLabel + + name + lblCTime6 + + + font + + 10 + + + + text + <CITY 6 TIME> + + + alignment + AlignVCenter|AlignRight + + + hAlign + + + + QToolButton + + name + cmdCity6 + + + sizePolicy + + 5 + 1 + + + + font + + 1 + + + + focusPolicy + TabFocus + + + text + <location 6> + + + toggleButton + true + + + toggleButton + true + + + + QToolButton + + name + cmdCity4 + + + sizePolicy + + 5 + 1 + + + + font + + 1 + + + + focusPolicy + TabFocus + + + text + <location 4> + + + toggleButton + true + + + toggleButton + true + + + + QLabel + + name + lblCTime5 + + + font + + 10 + + + + text + <CITY 5 TIME> + + + alignment + AlignVCenter|AlignRight + + + hAlign + + + + QLabel + + name + lblCTime2 + + + sizePolicy + + 1 + 1 + + + + font + + 10 + + + + text + <CITY 2 TIME> + + + alignment + AlignVCenter|AlignRight + + + hAlign + + + + QLabel + + name + lblCTime1 + + + sizePolicy + + 1 + 1 + + + + font + + 10 + + + + text + <CITY 1 TIME> + + + alignment + AlignVCenter|AlignRight + + + hAlign + + + + QToolButton + + name + cmdCity3 + + + sizePolicy + + 5 + 1 + + + + font + + 1 + + + + focusPolicy + TabFocus + + + text + <location 3> + + + toggleButton + true + + + toggleButton + true + + + + QLabel + + name + lblCTime8 + + + sizePolicy + + 5 + 1 + + + + font + + 10 + + + + text + <CITY 5 TIME> + + + alignment + AlignVCenter|AlignRight + + + hAlign + + + + QToolButton + + name + cmdCity1 + + + sizePolicy + + 5 + 1 + + + + font + + 1 + + + + focusPolicy + TabFocus + + + text + <location 1> + + + toggleButton + true + + + toggleButton + true + + + + QLabel + + name + lblCTime7 + + + sizePolicy + + 5 + 1 + + + + font + + 10 + + + + text + <CITY 3 TIME> + + + alignment + AlignVCenter|AlignRight + + + hAlign + + + + QLabel + + name + lblCTime4 + + + font + + 10 + + + + text + <CITY 4 TIME> + + + alignment + AlignVCenter|AlignRight + + + hAlign + + + + QToolButton + + name + cmdCity5 + + + sizePolicy + + 5 + 1 + + + + font + + 1 + + + + focusPolicy + TabFocus + + + text + <location 5> + + + toggleButton + true + + + toggleButton + true + + + + QLabel + + name + lblCTime3 + + + font + + 10 + + + + text + <CITY 3 TIME> + + + alignment + AlignVCenter|AlignRight + + + hAlign + + + + QToolButton + + name + cmdCity9 + + + sizePolicy + + 5 + 1 + + + + font + + 1 + + + + focusPolicy + TabFocus + + + text + <location 6> + + + toggleButton + true + + + toggleButton + true + + + + + + + + + ZoneMap +
zonemap.h
+ + 200 + 400 + + 0 + + 7 + 7 + + image0 + signalTz(const QString &, const QString &) + slotIllum(bool) + slotZoom(bool) +
+
+ + + image0 + 789cc4bdd772e34ab6ae7bbf9ea263e16ec5096c7973712e442f2fca5066c7be8025e8404f82da2f7f3273fcff20c45255cd9ea64f7760b23e024c9fc36526f4bffee75f6f0fb7fffa9ffff55ff345b0e845ff8ab260f6afff8997a3d1e67fff9ffff7fffed77f1fededfdebc05e07e707ff3af8efffe7bffe3b4aff15fdcbdb33ffdb3fb39c2ec887fb96e3087cb4bf67793c201f9c5b0e1ec1677bee7ed822cbf3c944d9a53f69930fdcfda8098ee4f7d991b27b3ede9025bd75872cf9373fc887529e27e1fd3d492f682bbbf4bc2a59ca138cc9529ec903f9c8d57fd8051fa17e4db2fcdeab91e5f7f1a7b22b4f780d46fbaca660d47790081fa0bc9f6764f9fde6068cfc0728cf01d2f39ec892ffec108cf4d7f8fde19eb45f9a3b36bd23fddbe8928f02777f4e3e76e363d604b33e9760f4e7ea992cf7177b64e98f690f8cfecb1764793e2f844dfd5c7af33159ee8ff03cebbb7e5576cf0f62b294675903a3feab1659f29f3c29bbe73f376469bfd695f021c6c700ed7188feaef7c128cf12e53f42ffad0330faabf96ed98eb63475edb10023bff12959fa231b9065fccd2ac21c0fe10559da773e25cbf3f13518e3d1e3efcf24fd8b5b30f20f5fc8727f3e5496fc9ec952fe7e57f810e5f944fdd83e9f8764493fe7f3ecaf09599eaf8ec892de2a07a3bffaa9f011e6e7ba0d46fbe7efca2ebd9a3c6f66c3e9a14b9f7c24e37b5a05637c0613b2dccfdec1189fe32159daa7be4796f6a8497f9af122ed9f57c018bffd108cfa0d911feb37dd234bfdfad764997f952559f29b838fd0fee34730e64f2f26a3fd5fc148bf3e5696fe43fb1c433e3402f0b1b46ffd982cf7ab48eff85ceea72e3d333ad1bec3028cf64c783f121e84e41357bfe041f810fd9be56469efe0932ceddb7c261fbbf4ba2bb2b44fbc00531eef9125bde246d9d5bf9290a5bd7bfb60c8d3f4912cbfcf3764298fd75076e5194dc9529ee0058cf65f307d8ca7f5a9b28cff0959d25f5f90a57cc5bb30e743109025bd694bd9a5d778214b79d2148cf1d9bb214bf93fd11f47d0df692c7c8cfc8673f0b1ccdf06ca777c8ef183f63f8ee57ed7c97f636ea03d920e18f5a92f850fa17fa615b28c8f469f7c1abaf6be071f49fb2443b28c87ca2df9c4716345167910cfc1d45763b2b4d7724096f4e76f6429afa7bf97fc965764296ff64a96fa2e593ef46fb343c6f8699225fdd654d9a5df3f163ec2fc5c4cc8f2fbe593b28c3f94ef08f65ad12523ff6bb2fcbef1a42cf9dd90a53eb31a18f2ba774686feb852167db422cb78acf695657cdf9225bf794696fa2f781ff269b8244b7a9348d9ddaf2664496f21f3e99ce375ec298bbc8cc892deb04686bd575576e9e523f031e4694a96df8f7df039e4d70559ee2f36e018f213e3e9e45ce475712e7cba0ff93d134e53e1aeebbfc3fd038c87e642f8d09820aeff7a60f457f3802ce33d3922cb78ec6560b47fccdf9fc9fc5adc81393f6365994f73b2e4e7cd94ddfdc93359f2ef2564c97fd817e678adf864c9ef739f8cf46a60c86faf4e467b5c9131ff3c30c65fda5076fd9f1d93213f06ca529e53b294273d5076f7eb73b2d4a7f108e6780dc892df22254b7e41ae2cf9b13e68ef0998e377345376e9ad33b2a47fd1274bfa953d6599cf9a1ef41bea67c6b3fbfdac4796f45a3764c8939c8cfe417b1f9fcbfd469b2ced93a3fec7b1a47f714686be8dc852de02e3f3641ff3e95d599eef8031ffe647cad21e0f60e89f5ea82cfaa94ac6fc7d5376bfaf3f81313febe7caeef7eb3a19f6d38bf0e9bedc1fd7c89087b7c2692adc75f2ffd0e803990ff501f9cccdb7f10959c653510163fe345265f7bcbf20cbfcf77365b93f23c31e92f960f403f469a6ecfaabda214b7ed95059d28bc8925ffd5159f4f10359f28b0a30f489774896fc2f5acaee7e5127e3f70918f3353a26cbf84a3fc992defc4359c6fb9c2cf52998df9994bfb55076e59f0664c827b60fe667d6274bfee303b2e4df3f54167b94e9a1ff9257b2a4df45ff72be365f9545de5d9165be6dfaca222f5ec8927f0fe5e1fc1d256449ef624096f2ccf6c0e7f2fca64186ffd2264bfea39ab2f4e70519f56f29bbfb338c17cefff11d19f6fc5059fcaf902cf9d76e94c51eec90e10f15cae24fe8f3529e96a687f120f3f99cf265305576f90f32b2e43fa82b4b7f60bc51fe2c7d65b117f97bd80353f4c709da735e5116fb84e9419e64ca529e19fad7c813493f06c3de6ebd9111af5a2b8b3cc4f3690a7b2d22c37eba5096fafb64296fd821cb78f5ddf83b52fded4f8439ff570559eed7d760d81f9b800cf9b15276bfafb7c9f2fb0519f3797c44167994be9191de81b2cce70bf2f991931f6764497f7d09c67cee75c9327e8a3b65773f9c9325bd6241867f5711e67c0d2e94c53ea99125fd68ac2cfed63359d20b1be063e98ff11919f6415559e6db3b19f6fa8c2ced5f63798e215fd17f9cdff3736597de8af9637e7fde288b7ec778e07ccde7ca321f3d32cadb5196f938254bfae395b2d8a34b61ced7a44f96fcb25365f77ce09125bfe158d9ddaf1d91211f6aca521ffe1ef2334dc892dfa2af2cf2e8810c7ffc4559ee0fc8925f88f63b813f508c945d7e454496fcaa17caa2efeec8925fb65096faf5c0901f0b65941ff99fa23d1b7764dc477a942721ef439ed53d32e4f3abb2f8bf28ff29ecab75830cfbee130c79d77a5516fbeb830cf98cf97c06f9d728c8682ff4ff19e4dde6168cf6ad67c2947f2b9f0cfff3932ce51b6dc8323f2ea4fd02da0fdd3e18fabc9b9345fea4cf64f8fb32bf8263d853e92b599e8ffbca4e5ec55db2c897fe800c797a0fc678eb0f95c57e3b204b7e8b4765977ed5274bfaa9fe5ed2ff9c81319e3653b2cc0faf45467d06ca2efda5fe5eeab7395476f7d72cffb9e41fb3bc9017930a59eab79a298bfdb221cb7caa9c2bcbfcd7fb90779a3ee2455764c86bf417e5c5c5882ce9e72d65d13f7db2a49f2f955dfa952332ec79948ff2242ec8f0bfb62cf3774e96fc070fca62efb13ce8df55872cf569be80212f862bb2e4d77d55167d744b96fc96e7caa20ff5bee4d7bf5276f59b37c0e8afe05559d23f25e3f7b7caeef7b9d80701e55174a1ecda6b724b863d365616fdb44f86bff948867fd3204bfe6106a67df44696fc860b32fcdd2332c6c7842ce94f1230fcc70ad3873c9f9c9225bdd93119f67b0886bcfb8cc9f2fce6832ccf17d7c26768af39e6f319e4f30afd734679ef7e7f7c40f9d198828fcf23371e7db2dccfc660daef2119f264a0ecfa2f699065be2f4e9445deec9131df47ca2eff5a420edcfd614e86fd47c6fc4eeec8884f0dc9927f559f477e3159d2abd684399fd73919f6e4922ce9559e9445be8dc958bfcbc098bf69932ce363b165e94ffe1ef3f7f34859f2bf2023ff4f32e2f57530e6737caa2cfaf78d0cf91129cbf89990a1bf9ec9925f7eaf2cf26c4396f66c0dc8909f7c1ef37fd65296f9f94e86bd7ba52cfe34f3877c182d955dfe337d5ecab7667ba07f9be764f4475ff814f27c3e5296fe3921233e9829cb7c5f91a53cd33765579ecd0359daa77946c6fa1fc623e547af4586bc3f5716793f204b79aa7a1ff36f4996f2788fcae26f8dc9982f183fb4b7364b65f15f5ec9529eda87b2e85f9607e3e7e25459fab34746fbec2b4b7bd4c9d23e39e637e5d9f89a8c78c6bdb2c4ff597e8c9751ac2ce3fb4098f65f744b467b42be511e7ebe29cbfa668d2ce5a956c8529efc058cf6fa44f9cf604fafe764c8f38ef039ca5393f632f64de0e45b3d25433fdf8363699f2823cb785ee8fde8d8f11319f25bca63ec0bf89ff7ca2ebfe69a2cf2343e2363bded018cf157dc92a53fd71365917715b2ccbfd11559f2af8d94459ec764c9bf182bbbfb594a0e63371ffb64c427f7c1187f714886bdc1fa425e5d44cae2efcfc952beea89b2cb7f7c48c6fa47074cff735f59fc4fb60fe4d35cef4b79c6ac1fe453b05696fb6c4ff4efe7b5b22bcfe0890cf92ee353ed99784286fddd264b79962365975fff8e2ce5496e95ddfd6e932ce5493e955d79d26b32fae3088cf991f9ca323f981fe4d7aaa22cf6679d2ce51d9e2a4b79591f8eaf1b65b11f94a5bcf90319f27e09c67cdd4464c46753b2946f5a288bfed7df637dca53167dccfc31ded62d6577bfc7fad35ec17ca33c9b4ec9f0ff1f9525fec1f6c4f80ab62cfa86ed83f155cf95a57d1a64699f19cb83f19443bea8bfac0cfd744c96fe1d0764c47b06cae27fbd91a5bc83a5b22bcf28224b799ba8ff19e3057b64c85b5f59f4cb0119f6f5bbb2c4933664c9af1882195f6d91e11f27cad2dfb764d8479fcaa27faa60f4d76757f81cf37189fccf519f02f3f71cfaa1e1daeb44edcd2e98f6e5a2410e45debf2b3b79d8d4fb22ffe77a1ff27f0386bc5d4ec990f7e7caeefea24a96fc92bab2cb2f5c9325bfe69db2bbefcfc918df2330edfd0765d1ff4db28cc75eaaeccab362f961efa7beb2bbef6bfa689f58d99567119151de7d65773fbe27c39f617a984f9f4f64297ff74c59e2032159ca3f59288bbfc4f689a5fcd3a6b2e8fb822ce5f79f9545dfb1bd313ee24361cafbfa0319f18c2a19f19696b2f85f4f64e89f4259ea9392a53e5e57d995b7abbf97fa7c2e94dd7d2f21c3be45ff51be476b32ca575516f9f84a96f279c7ca222ff479f817a9b2cb3fbf234bf95667caee7e634c96f6f65664ec8f63f930ffb31e19fe4740863dbb5176e50b876429ffa0adecee5fccc9d0efbeb22b5fa2e9617ebe91111f3c01435f041d32f4c54059fc17f61ff4457aa5ecca93bd90a5bcfd4cd9dd1f3c92115fbc57167b44d3837db4274cfd30ed92a57c9b2b65f11feec8586f4d94653c7e92a1ef7d6569cf942ce51b5c2bcb789890614fe760fa5727ca629f0fc8f0f72265f1173a64e8ff6b65d1bf0b32e2bbb7caee7eed812ce56d7864d827187fd43f459f8cf5ea6b65f13f0332e27b4365591fbb20c3bf7a22a3bfa03fce389e6232f469ae2cfaac49867ff9ac2cfe25db13e3677a4f46fb63fe9d233e57bf5116fb4b19ebc785b2dc0fc9d0b71565b137347dac5723ff73ee4f6992e14f8e94459e7e92b11f0aed7f8ef8dc6c4ac6fafe868c78df5259ec872119e31ff2ec1ceddd833c08b85e74a5eceeb7d0bee101f6fbc87c54ff6e5113a63db0e890e10fd6c1d0dff1982cf7fd776577bfd620c7723f234b7e5e0f0c79b578258bbcaa2e94453f4fc9d06f89b2d80b2959cae3dd2acbfd980c7fb405863caa9d28bbfca29c2ce5f1c7ca529e908cf204ca2ebf19eb0f7fba3e5596f27864acf748ffa8ffe46564ac1ff7945dfed543b2946f73a12cfee63119e57b50167baf4a46ff0dc9529ecd040c79345c9361bf7c288b7c8dc9b05f96caa28f4ec852de40ef4b79bb7a1ffa342263bfff080cf914337fe8c7d99bb294e7920cfb63a9ecf26bb17e186f599d2cf9a70519fdc3f683fc5a35c9588fd9b2c42f72b2946fd85396f5b657b2942f7c5276e59b6dc852bee64c59eca30519f6bed8dfea1fcd2e9545ffde93e14f46cae26f1e92a19f17ca2ebf8b0a59ca53cb9525bed225a3bf8ec0908fd1a1b2c8bb3732f6ef1c288b3f3423233eeb298b3ed0fbd0e70365f1cf347da9cf455d59e2452c2fc6e3469f97f95163fbd19e9b83e9df2764ac575d90a5bc514b59eccd2119f37bad2ce395fd87f1ba0a945d79e737649407e353f52dfb13e3336a90113f4a95c53ede90a53c134f59f4ef0719f379cbae3c9fec2fea0f945ff5e9a9b2ec476b91a53ce38eb28ccf828cf97ca32cf6c73559ca9355c8680ff417f5ef608f8cf5d40365b1770ec9d81f74a22cf615cb8bf17571ac2cf18f902cf9afd0bed4e7d11d19fb95efc9386f72a82cf1a39c2ce5b9785196f6d907237ebd7e57167b93ed037b6b33579678d83319e977c9904f6db2d46782f60c604f557232f253c6fa41a12cf61dc67710c03e86fe0b12c4cbf07c7880fdbc536591aff764ec97417b8427d80fff41c67905e8b33080bd83f998a6287f4c867de6c6ffe9e1c939ec932e19f6491f0cf9bb08c9d0a797caa2cf0764d84bcf64a4df23c35e06535f0f876449af1f90613fe87d496f9190b17f6209867cebc664493fb9244bf9c38db2d87b6f64c92fce94a57e1764d807cc1fe3b3fa4286ff14288bbc5d93a53dbb756589ff3e91a17f3d6597fff2992ce54b6764ec4f5980195f7953167f7a4c96f275dbca22cf5a64295f63a62ce55b91a57c9f7bcaae7c05cb87fecf3a64d89b5361eadfc140d9956ff242c6faf1908c78cf4859e26f0bb29467d55676e519b6c8b05fd0fed4a7d14a59ec910a19f6c93b59cab33c5596f1744396f2f59764ec1fac8121efd6a9b2c4ef1b64d8733332f4e389b2c4cfcec9d08fb1b22bcf94e5c3f81a4f95a5ff8ec8d8dfcefb5c0f7e24637f7ca82ceb056332faef4c59e21f4f6429df66a62cf67a44863d3750967852872ce59ba17ef4579b2b32ca1b92117fd1e7a57cabb5b2bbdfa893d19ffbca127fd1f4a57cad3bb28ca7cd1319faf6100c7d9ab6c988cfaf95453eb4c8d03737ca626f7864d89f97ca62affb64c4e34ec9523eaf20437fb13e187f514d59f407eb8ff1377a5616fbe89e8cfd1d81b2c48b347dc49bc9184f3dd61fe36978a22ce399e9613c5d1c294b7c654cc678bf264bfdd790bfd4c7618f8c784b5759f4ed862ce5697acae2dfbd93610f1e80113fc823b2e8dbf05e59e26f2959f2af79ca627f3c90913fe445007d1db23eb017ea1d65b127987e80fd627c1ef6c46245c6f9bdb5b2d8eb4f649407cc78c8649f8cdf1f2bcb7ada1159f2af8f94253e73053e91f84bf4a82ce59b91b15fada52cfdf349463c13fd4f7b66caf2a27d366b6591a7e88f10edf13927e3f92365292fca43fb68b626a3fe736529ff1119e759dfc9d89f25fa23a43d525d81313fbb1118fa7cea93e3c4c98f7732d6a32760c8c7e48a2cfaae3b5276e97d5e92612f1d2abbfbf92d59d21fa1bcf46f932659e657724d96fcf20b6597dee88d2cf9452764e8bf1c0cf9d57f2763fde94559e46f9f2cf9d526ca22dfeec892fee0030c79145f91213ff53eecaf4f32e21d7a5ff2afec9325ffca48d9e53f1892a5be3dd61ffdf5790c867c4b2fc9224f6a2fcaa24ff7c858ffdf90b15e31509678c7940cff3c224b793ed97ee8df3eea437f336f90a53cd1a5b2ec975892a5fd46afca92ff2959ca57a9298bfed6f4a4fd96b7cad27ee764d8631918f2721393b1be169011df4895c55e9c93b1feaee94979d75532ecc7576529ef1119e57d274bf95a981fd4876bd617fab03f5196fd1d2f64294fe54e59daef8c8c78cbb3b294674496f6aa0ec9d84fd003733fdfa7b2aca7b0bda06f972b65991f6c0feee7f395459f2fc88817bd2bcbfce4f8c1785ced91e17f883c0da98fb31332ec812619eb67a7caa2ef5764f82f1d6569df828cfd455565579e4d9d0cffe58a0c79fa00c6781b3595257ed423633dea52d9e51f307d8cc7eabbb2b41febcf785b9b8cf982f6a57e5f1c92717e305796f274c9d89fb2a72cf613db23c07eff9ab2ec77c07ca63dd08a94c59e66fd12e8f389b2c4abf43eec43d63fc17ed567658917a1feb4278a1519f652a42cf65448c679af4765193ff764d88f7a1ff14f8c2fda13cb5059c6db822ce90f67caa2cfafc992fe04ed4bfb6271a92cf649858cf35dac1ffa6780fe547b03f23742fd2ece95a57d30de687f4c4664d84797ca62afdd91b1bfb950167b668f8cf5cb6332cedb7e2a4bfbb9fe3e53ffba9b91451ed6bb6489b75c3c91b11f810cfd3cf5c8a28fba21599eaff03ee45da28c78cc4cd9a5179d9325bdea3559ca130764c4936a60c8abfa1919f6c64859fc65a60f7baaea298b7edd274bfe69870c799708533ff61fc9b02fce95451f55c888575495653dea842cf6daf2958cfddea81ff561ff4959e2c3fb64913fd3908cfaeb7dc44fcec8883765ca2eff16eb87fe5cadc838bf3805433f161f64ec7f7c54167b88e5817eecce945d7946ef64c8cb0b65590f5a90a5bc9b336529ef2559cadbd4fca43d9b5db28c9f44d387bd8ef940fd387f5496fd552d32eccb95b2e8f70d19e729f69565ff04db8bf6fb5ad995af32264bf9f32119fb95303ea84fa31919ef0b682bcbfee63a19fb93de95c59eb923e33cdab1b2b4f72d19feb6de97fa046f64c41bd01fd4a70b8f2ce5aba4ca128fec93a57cbda1b2c41f3ec958efa892d1be15b2e43fc6f8537dd9571679774d86fe3a5616ff7f8f8cf8edadb2c45f3232e2e1e84feacf755f59e4fb920cfd79ab2cf67641c67993a6b2c48bd89f09f6678d9565bf00ca437db9689161ff7595c55ef8244b7ed32b6577bf35244b7ef51e18fa74fe42c67ac4a3b2c4173664bc2fe34c59e60fd33f813e823ca53e0d4ec8d0a735b23cbf84bc0fd19e4bd4274279466d32f6933d83a18f43c803f5e7bb64f847556589c7f5c9189f0fca325e3ec838cf2eed13aafebb2763ff68050c7934fd24239eb80786bc985c9325bd7a5559f4d3922cf26c7d424e4edcfc1f91b19e83f4e9df855332fc8f2519eb0d2f64c97f38529678c30759e217b52a3911be22a7ae3cb34459e4ed06ccf59a1a19f6c85859f67ff2f7d057515f59f6e3a464e8eb9eb2bb9f9c92a5bd86976429af7744c67ac51c0c7d54c4ca529e0e59cad31c298bbfabf7a53cb5736559dff2c8529e4a43d995a7d1244bf93e5764ec7760ff41fff4d85fd03fb3bab2d85b8764296f7fa62cfa4759cadb8a95ddfdc60159ca9b56c8d84f89fea0fe594564c4132664eccfc9c8b0bf1e94255e35234b79066fcad27e4db29467d35176ed35d1f2c05e5980a18fb203658937b4c988d7acc8d2bec323b2947f744d46f93f95653d8ce5c378ac687e684fd617e3b1b1afecca3ff4c868df4730f455fd990cfdd4204bff8fee9425fea58cf973ad2cf3794896fc830118faa9c6e7a18f2a5b96f4efc9583fa92b4b7f633c515ff54664e8837b65f127dfc9d87f7345c67ee99c2ce51fa3bda97ffa1764e88f076549ff8c8cfa1c2bbbfc8a13b2e47781fe08e97fd7c958afd823e37c18fa23843d50f92043ffb7c9586f785396f39fac2fdabb1991218fd03ff427375d32f66ff860e8c7f10519fb1f301e23d46701a67f99e764ec9f8994657f6e8f0cfb527f2fe5dfbc90e1ffb9fadad747897ebaa881795e600286fe5a56c988272f858d7e71f7c385b21baf714e167d130d94455e3e80313f9367b2ccbfd92759d2f7af945dfad1902ce98785b2e8d77d30f48577a02ce397cf435f5c74c8220faafa7b294f375176f9872bb2942f592abbfb498d2ce5f38f94c55f6d81a10f821959e45372ae2ce725a664294f76a3ecf21bb0fdd05f4955d9dd9f4fc8529ede4059e2f73d61ea832c214bfb142959cad77f5376e5ebf964f873156597ff6c4ec6783a5276f72ff4f752beee9db2ecef60fe5cffdf23a37c3365d1f7af6429efa8a52cfa2a274b790797caae3c59832ce54d0332e22dac3fe47d764646fbed93b13f235216f9c8fc02295f3653167d744a867de42bbbf2f51ec952bec689b2bb5f1c93e1af9221efc22a59e4c5e79a8cf3496c3fe88b569f2cf5199e2bbbf2663532ec83a6b2bbbfee9211bfca955d79bbecdf04fb0d503eeaa3bcae2cfb0b6ec9d0b73d32e21567ca32dfa76429ffbcab2cfaf6950cfbfa4259ee9f90a5fca33119eb3bbc0ffd56657ed05fe32bb2946ffeaa2cf12a65d80337ca321ef43eda93f99f487922b617e3cf0365b1ff6a64c44bd6ca120f3b224b79aafa7b29cf7aa12cf1408c67fa7f8d0f65d177ec2ffad37d32fcd92b65592fb826c35e867e88d0ffcb0b65d9bf7a4c863e0e94e5fcf7848cfdfb4d65d9bfba0143ff6e86ca52fe3e19f1a71365b10794e1bf613c517f176b32eca95c59e23d900f11ec91568b8cf7e7bc9271de15fd17239e30817c8ae1ef579fc8386f84f68d196f91f112a9bf7a284c7d9d7f9245fe0e07caa24f8760c8cfe61159e4cfea5c59e453950cfdf7aa2ce97960e8d35a850c7dbfafeceefb7532d26b2b8b3db107e67eb71659e647fd5559ec934732f2d3e791df0d19f93595c51f15f91251ff250b32e2e16d65b1074664e477af2cf9adc9c8afaa2cf6d82518fa2cbb5696fc5764e88b86b2ec67f8204bfede5859fced9c8cfc5f94a5be2c2fe441ab20c3bfdf5396fd012c1ff5d781b2e437214b79bac7cae22f866494e74c59fcaf0e18fa69c5e7a99f9acab2dfe3882ce55d2e95657fe22159cabbbc5316ffef930c7bf952d9ddefb3bd1394f75459f623a03d19cf9b1f90b1ffae5096f8cb928cf589b9b2c4d7db64a9cf7aa52cfae2980c7fd65796f8c5882cf5691e2a4b7d1ec8187fbc0ff9b7627d20ffaa4b6589570764c8df2b65a91feb037d37b95776e59fe8efa57e17b1b2d4ef8d8cf17546c67e06f417f561dc5216ff8aed017db80894c5dfd4fb58bfbe5696fdb95532e6c35c59ec2165297fe3990cf983f94efd387e25e3fd0e97ca521e8f0c7f3b5416fb82e5c1f8dfe8efb13f08fd4dfd39fd204b7e6bbd2ff9550ec9f08fb62cfb2f3330f4e3e8932ce98dbbcad25e6332e25f3d30faa772af2cf1ef1919e59982d15e2d9697f18f7765d1efe2bf44d497f30e19f93d90719e0df9c7d0ffb3828cf533cc57ead3cf5b32ec2df44f0c7ba82ff64594c0ffbf70e32b50fff4e2044c7df6a62cf1b15330f493e72b8bbed823e3f73565895fdf0a53ff783764e89f4f65496f49467a1565594fe2efa16f8a07b2a4ef9f9391fe9db2dcdf9091feb5b2e8ef7730e64b75ae2cf91d90a15f5f94653eb13cd427fa3ce2114f64e47fa22cfe78138cf935e07de8871edb03fa21592b8b7ecfc9927ffcac2cfa83f5877e882f9445be5e09539e77f7c9925f912b8b7f3a254b7e595359e2012f64c96fd55596f58f1618f3b15e21633df45059fc697d1ef1990b65a97f4196f2543f94ddfdd12519e313fd45f91ab33e90a7d51e59dabfb2224bfed51919faf851d9e5573d2643ffb6c19097d32159f21bb1bdd0df9b7332ec1fcc4fcacb6843c6f9c36365592fcac09087ab4459d677f6c858ef3927239e3157167d1781210fe757648cd791b2f83ffc3de395a9b2946f46863fda5416ffaf4b867d119271be0cfd4f793a8cc890ff6b65896fed93b1ffef4559f417e415e56db1a72cfbbd1232ec8db1b2e8871b32fcc71365a90fcb03791d85cab2bebd24637de4942ce94d30be13d477b352167fb44146ff4ec028ef27da37c17aea6ca22cebcb4764fcfd12942f813ed9ec29cb7ac30919ed75a92cfa1ded9142ffb4d6643c8ff19b32febca72ce5b923e3f94259ce6f407fa4287f6b45c6f9815730e2d3d35b32fe3e83c817f5dfa63918faacdb50167921e5d9fa471fcae24f8ec0d4378f64c8bb180cf9d0ef9125bd60a12cef733806437ecf07643c3f5596f8a9e82fb5cfe70bb2c8a77ca02cf9f7c9a8cfb1b2c4e7f93ce4e9f2902ccfd72f95a5bc4f60e8c3594a46fdc53e30f61bf69b77c0f87de3168cf13ead29cb7a92de17f93446fb45186fc52119fb839ec9d80f22f233e2fcaf5c2a4bfcae4b86bf93298b3c7e24633d3400637e5d3494259ef64cc6fadb81b2c88353b2e4377b5596785f878cf833c61fe5c3f05659e41bcb8bf69b1f2b8b7cab90e19fde8369ff6f59e2435332d6afdaca12aff3c8927e21f222a27c5a3f2a4bff74c888ffc5caa22f3232fa674dc67903fe9ef1af2e19fec3b5b2accfeaf3925edd5796f640ff50de8581b2f89798cf946f832365799f418b8cfebf27233fa497c2fe8fde9465bd6f4ec6fee64f65592f3b25e3bc39fa93f232ae2bcb7af53e19fe42aa2cf24f19fa6002863e481265492f2323bdaeb2f8276764b4ff81b2c443d0ffdc8fba6279b17ed88f9465fffe1119f1f65365293feb9f227e112bbbfc7c977fa8fec7c5b5b0c68f8ec19047bd3e18f2a1910b53fead6ec0987fb5028cdf77ab60fcfe2211a67c4b6660cce7cd3b19fb39eb60ccc78b1b65896fbe91112f1d9345beae9fc992df300463fc5d0cc9f8fda330e5df305596fd9fd764f8efafcaeef7171f64496fd40363be4ddfc9b09f6332f6bb64ca120f5b90b15fea098cf1b4ba5316fb6a42463ce45059ca7f4f463cc45316ff8df5817fd75a92a11fd0ff31daafd75616f97441c67ee837658917a17d29efd60519e75146ca223fd7649cffa82acbf98a3b32d68b4ec1b43f1f9545df54c8d0370fcad23f3119f27f0ac67caebc9125fde05459ecfd1e19fbb1ae9445ff34c8d21e6bf40fe567f55e59dedf9092b1bff25859eaf342c6786e2a8b7c3922a3bf1f94e57d43283fe5eff45259f6675c91b1df62a32cf6784086fc8d95257eb447c6f95b4d1ff1b90b32c6cb2d18f27b5e5396fdb9af64f8077bcab25eba4f46ff687a58df6b90b1df06f389f27d5c5796fc5ec8d07fe7cae2efb07de88fec2b8b7d3526435f431e51de4f2664e4c7f240be47efca72ff838cf63e5496f1c7f2a788e70ac711e39b4365d9ff7749867d2af339a63c5bde80299f0fc890574d65777ff506467d9b9f60c63f5b64e9efc65a59e2070119fbb9a5ff63ceefd6b5b27bbefe4e86be40f939df7b8764bc6fa0a62ce393bfc77c0f3e9465bd81f9a13f93900cfd9028cb7e822519f18a3365d99f7744c6fa06f3c37c1fbf90b15e992abbf4c30732ecff3b65912fc764d88387ca32dffb64c97f8efae8fc1e2acb78f3c888173c28cbfac0868cfd3b6fcab2bfbf43c6fb5c3f94c5fffa24a33d301e39bf477bca32bf591eaee71e298b3dfb4ac679923b65699f2619fb4fd17f9cefeb3332ecd985b2ccf76b32f23f5096fe6179e99f1d2a8b7ed1fcb05e3f5096f9c3e7290f9ec990070fcad21ea76494c75716fd5090616f1f29cbfc70f2263ae6fccef6c8886f2fc15c9fb8204b7ff5de95c51eab90b1df2116e6fc9df494a5ff03b2a4378d94451e0cc9581f6e80d19fa33e19fee84259ca7b4e96f427beb2ccef2b32f68f7964f1e7d72c2fd79bf6c9381f74a62cf6c82919efa3fb501679552763fee5ca623f56c9a8ef1d18f3bffa4c863ceb284b7b303fceff1b65b127597ff45ff75659da9bf9a3ff5a1b61cefff999b29ccfb926a33dce95ddfdf49e0c7998294b7d4332f4c99665fdf4968cf5842618f33d7c27431e1f2bcb7c4fc992ffa0a22cfdff46c67ac6a5b29c37780463fe8f3fc9b02fce9565be55c9781f40a42cf2e9858cf6385196f1caf6c2f898b0be900715961ff2205b298bbce89011fff695a53d6ec8789fe299b2ecbfda27e37ca1e417737ef79ec988ef4b7faafebdb820cbfd6943d9f963cd4730da7bd95096fd767b64aca754c9f03f6fc068cfde0719f1a1aeb2f81be764f4e71919fb078ec1982fab0765b1cf9b64d82327ca22ef7c32e6abf4b7eabfa84296f47b47ca22ff9ec8d82ff2a02cfaba4d46fbf5c890cf0760cc87fc9c0cfbfa912cf94febcad29f5764ecbf5c2b4bf9fa64ac27697ef0f7311e38ded7e7ca220f7332ea5f5796f68bc992ff67a62cf547fb6a7c6345c6f9b6b5b2ccbf4f32fcd389b2d82b1764f4f74059fcff1a59ca131c294bbcd1b57f6cf585f4c70d19f6f30318e36bbd1166ffc62b30fae3d32323fed026e37c46138cf6a89e91a15ff7c1a8efec4959d68f5ec9902f7a1fe7a39cbeb2e623f6433bf994a687fc7b9e9f60fc7dd3e61e187f8f74b60fc6df0f1c8f848ff0f7bfa32e19f1a04730d2db8460a417d6c1fcfba4488f7f0f6c81f2f17d7bfe1318f12cff5698ef93497c30d7af4fc17c5f5f00e679af8130cf6b072b30cfef1e81f1fb10e5e37efb654f98efdb0a2764a43707f3fd8f4b30de2fe577c8c88fcfe37d157e838cfaa27c5c5f096330deb73454c6fb8f3c6549af20a33f5ac2f407ab684fae0f143561c6bfd2088cf1df457d192faaa0fc317e1fdf0827905f33b427fdb5f1828cf5894732f46548c678dc80217f669eb2c4bbe664e8ff0b32e2917760f85ba34765c97f4896f4c3b6b2f837ef64a43f23a3fe180ff4afe6cfca12ef0fc888f79f298b3dd725239e74a32ce5fb20c3de7c21633f08fa93fed3e4848cfd4b67ca223f4fc9a8ef87b2d4f7958cfa56c9e8ff6b30fca7f14c59fc15e647ffe95859f425db03fd19be294b7ca34d86be3f2763fc62bef3efd7171764fcfdda3365f73ef5b94796f76fad3f94e5fd59cc0fef97984c95e57d1b0519e77f626589e73f91b17ea0f7f17e943b32fc3bcd0fef676a90d15e27ca62ff1e92a1efc6caee7e5c234b7bb5176469aff6c2f7cc15fcc39f21ae089ff6fbd85c49e9b9f89bdfa5f87ef7332971b7f43d7f97949e0b713fc3bf7b7edf1f80839df492d2efbf2b97fdfdb0549fd1ceef83d2bddd72ecd637ff4d7b8d4b57f84dfdbd523ebf6affdd76297f4e7ed35f7f24fdf137ed1deee4bf5bff292ef79c3f73cfcd7ff1fc3f3d3eede7e2bbfc9d8e5cfa2b7f6dae7feeb370d7c6fcfbd3bf3057612eb95fc1fddde7d7ee372bbf8aefed674d9fdf5ef6fbbadf70df37bffc5eeed7c072bfe1b75c190affd27dd7f8925605d715d2bb362db4c13337e6f3c6a56feb51987f4b7d58cea596bfd06bb9736f7b15a61cf6f7b7fe1d9e633ae5fadb72dee3b35cc6efdae177fd50be6a680f9bcf9de98f1fdb7fa5e5bfff52aeef3e0bedcf8abfedcffb9dfefbd5657fffe09e6ffce4996d7b7efff9d7c66745fb93fdf1257fe891ca7fe86a62ced6c0b5d2bfffc8f5b367af77f2a8eedcaf969ebb0657f16c7327fd72d9da25661e6d5cfcee71a75cb5f61faf57f0933afebbd75fe913ef37f9fed17ef9ee77fcf76e7fec3ecb3e68fe0df5f92bd777fd51717a84f3ff9fba6aa57f37fda7bf31ed0232a0e1744913df55dd2532ac82cfaa2f7aa6897f3f9b675ebe2927afb6fbae81ef1b861bf8ae70f71ffd8eff6a3edfcc67ed17e97cdf1e52eea5b131a8e37ef6fb1af2fff1bb5fe7f1abab59fab72dc3aff3fe23fddbf8f2ecee6fd91f3faba7fd77fab78d893f333e7fd91fd0237f4676fdd9ebfd1f9493d4212fedadae28eb107e36db5f75c9ae6c2beb865a296d7bb54bdf7ffc442efe4e27f07ef69be7fe48fdff6c3f5066277f639a3f6b8bea6f2eb66dadbdd5ddffc9eb97fdf11fd32394174d3ffed3f2ef67d79e91637bf02f6efcd50f3a64cf5f397bd97eb69ddc6f38b9b5814ff1639a0dc89595bfef6ceb95b3af37ed057c11eb03d9fc3a4eb7ecca5dfa5fbb32767b15f88c55a6ffba3d98def6f3cfb4ffae6e123dd22b95f7df4bf7bbfeddcd8f3e5455afe287ebab1ef9b1bd7e97f7dfa147e492fed8c9ff3fa447ca7333fe66feeecaca5fc9e3b2cce17560ae433cfbf84dde1fa5ebed9b72354b97956b47f83c36d789b94ecd75d6deea277e5fd6477f468fa43fa9ff77bfffbb64fd6e9af1df90f6aecefe553b7ca747fea89cff27dae067fdf1558f70eefc539fb4e1a94776e76a59e6574abf235316d397a8224d2bdbcffdc2f3cde57981177a91177b89979acf2eaecc5c3dbfebf5bd813734cf8ddcf32b3f94dfbadfe7a56bdc5e78137fe54dbd9937f716ded25b796baff0367ec3fbf42ebc8a57f56a5edd6b784df3df9677e95d79c67af3c6b0b96d393f4d3a37285fb5549ff225df79dfd67fb71dfeeae7aff4c89ee98fea5f4c9ffaa11c8b2cc7debeaf7bd94f6c78b7ae8f79fd7a7cfcddedb4db1fdfeb91ff44ccc0cadc6bccd51afe6d3f1f71bf1c43aa959ea7bfc0989491dfde9db94c3adebdf7e099df798fde93f76c3e8d9cf73ae67a3597d1179ef17d3ca33bbc3d73ed9bcbe81bcfe81bcfe8096f692ea30f3c9b9ed1139ed113de797b11f8e6f2822008cd67642e23670363b30726bfa06b2e63b3063d73f5cd3530d730180579300e269089a68cc1d45c3329abd6f3bbeb3b195e29d5b91c437bdcf9aeec5ffdaeed77f32dfb54ec8f721ffd913477cb5bee2ffebb9cd775a9dcd7edaf7dfb3bbdb0fb1c7ffff8cdbd3f73edf6c7171de3f4c83fa943c4de6e409758fbddf3afcdbfad1ddfb69fc1dc7f7431a9225848ecc87c16fabb1b534a895d17c1325805eba00836c16770115402332203634706c637081ae6dfa6b5825670195c994f3b52cd6f83dbe02eb80f1e8276f0183c05cfc14bd0098c7f11bc066f819941819941819941c17e701098d91398d91398991398d11d9899139899139899139a99137ae60ac2308cc2384c82bbd08caeb01b6661cf2fc27e380887e128ccbdbb701c4ec2a9df0967de4338f77fee13548c0ca74d5c928da6fe2bdb53a1fdb4b2f9daef04263d7f6dbe3333db5fba36e9189f6865effd2159fa35dfad5e5ea20c4d97966977d31f6dedb7af9f3f4bbf8998a2ad832de3ca94ef0e7aaa5daabfa953b030e98b0e93b860536c8c70fd93b2d65cb9b6e5603bd577e28c7f872eb1fdf18ddefb0fe991b2dd9795e40bf548bbf4ec6be99e19e96161ae4df8195e984f3b72cccc086b613d34b3226c86adf032bc0aed7337e16d68f44b786fae0773b545ee8726fdf0297c0e5fc24e68d20e8d7e09cdec08cdec08cdec088d7e098d7e09cd0c09cd0c098f65768566968466968467f8343325f2f1bc2ff723336ba2c05c46e74446e744460e4549308ad2a81bd97abefc42265386574a6dc38bb19e13a461ca1419dd15f5457f064bd155d4597fa8fd77ffbdeb8f40fe078bf6575df22b7f0097fb4d490f79617bebbb510f3c4a5f6adf7e7cd3f7bf1a3be5f8e39fd1757fa48d921d76ff767ae477f6de5ffdac610d416455ec6228120f6a4403730f32221afa76dda1509961d7246c4bdc44a3288fc6d1249a46b3681e991e89cc288956d13a2afc4eb4893e2333832253a3c8f44a548bea51236a46ade832323a2532694466d447b7d15d646650f410b523db63e7e6f3c9f0737017991e8d3af61eeedb7f9b1915991915bd476d37433ee4d3ce98684f668ad359360f33732233d3a2c3e8283a8e4ea253532fab03ef4b7eca5759bed523cd925c371c4ca3b3e83cf6632f0e82c28be2303a8ea33836e98ee32498c7c6df8abb81e890aaae0bfdaafdbf5e5cfbb1f1b94f5706892d5de39ee885dfa7cb4fd797ed459cc5bdb86fca672cd078e83762bb4ba7093db8b0fd6cbecfdd772ba343cc1808276e969872c463f4fb777a64bb9e23b1cbb69653c6c85f1f9fdbfe28ef65f8cfea9157c80cfb196ce58dde6feec8a2d7d2bfabb8674671b0095bb1b1fb63233b6363efc77373997bb19931b1d1f0b1d1f471116fe24ff37921f22c36e9c46ee698cf9ae8023baaed088f8c3e71b3c4c8b2b86e3e5fe43ba7233ea03b0cc70dcc0c7c67d93dc719637f6f4740cb702e7575656eb77f6e2f7f67ffe25e6446577c692e53ced8b4536c665b7cdb16bd62afa31df9fdefe891529bbbcf698929a37f27dbbf4b9fbec6d894f54e2ea74b76d7aa76d7ab5e7f925e6de7df657d52f647fe2e7db2eb1f7ed523ffa40ed9ca50d109e7f17dfce017b19103b1d119f1139ebb31f2c78c56b73fcaca302bd3f6cdfd67fcfecafcdbb476dcf18ee3d7f82d7e8f3fe2bd783f3e880f633362e2e3f8c4ea97f834fef0baf1997f629e3f4ffcc4f35749e0744b3b31332689e40a5a32e2a3a7244e9292ee30233f31d64cd28585e59bef5f4497b819f581d9716ad8e89c24333ae8499e4d7a493f1924c3c4ca4f2b23696fffce1fd9b58fcd8c48f23848c6c9246c25d36416cc93b95f24a67ec912a3b12d723ebef8c3edbf2b9b1bceff58fa17c67790f59f3be7f7358c0fd4713e611b72fa77b1a50fd809f6593b3b6cbb188995185f2a29bc45b289df92cfe422290c9b5197548dff68fcabc4cd2cf12792fa2ff54849af99df583b847e2af7eafdf5f1f9ffb33fa232d5c890c4c8e0c4c882a4158c12c8416b532797edafeb0d8861254696fa47613d319cd8d1736b678af934bd9118cb29b13d62d24e8c4c49ec2ce3da85e5e7e425e924af817dde584d8919ddf6ff8919e9c9de5627b811de9519c04fce06ea0bab2bdc73fba27b924c2c33ea94e440625dc9617264edeee4785be76fe3f1657f64477e3abbddd6d7d42336333c3915bda87e0af5d31fb5cb7f96bf4dc3b6fd19fac0d43335fa35e51eae3f2aa3e95742c7d919929a72a7462aa54622a5463ea7499aa656f20ccdbfe9abedda13df95b5561a43e5d859f527bfffb33a64d73ffc1ad7fa2ece5cf9328fff48eceac7b9f94536fa45da4bfbe9201d867974928e924e9aa7e37412ac8caf318adbde209da6337f1cdfbb98c8951fa7f374911ab999ae8c9c794ed7c9495aa41b634135d3cff4c24be2abb49256fd4e5a4beb69236dc6af693f5ce9da77c7c5cb6c9438f6ee5263a3a597f12cbd4aafd39bf43635dfa7f7f0ba3f4a3ae2cbec303a82b3e4743b2becf7cec27a828e319f96d387b49d3e7a51928b6c8cec0efafa4f657943f5c8fa9bf6bf36f74facae35695066deb876e47356ee769c9efa5d7fec7ecf7d6be7d1287d4a9fd397b4939c4747e96bfa16e5a61f56e9bbff893c7fb65ee16258a64f4d5ba546daa4fbde223df0eae9a1b7f2ced3a3f4383d496d9b9c491bdbd8606aaeae99815dc3ddc05b191ba1e31f3bbdf5d51fd9d52715897bfafbddb01b794137f687c9953f4f9ffc6137f9859efef7d7f1e2efc6ef377aa46cf7bde1bbf29e9ab25dc939cd58f80f73b0bdb5534d6b7553c87ac35d2353ba59b7d735b2b73b08465d2b5fcc68ec8eb6b2b26b6cfbee586493935155db1be63be393748ddceb1a9fa46b7c92ae9131dd6577e59edbcdbfb4aee264d789c8b8aef15dba465e7737a223e8777c99254f72515794f54af7b3e4a79851d23572be5b11d9ff4b3f8097ade377eb23bb6bbff40fcaedcc7581ddb6a77d5f96b52fdb7434ae64f5b8ed0373bf6b7edb35be983b07c3be2eade9741b320ed4f7a96dd3ed9a74bac66aed1a1ba07b25eb523602af31c363699feeb544cebb66b6778d1de0594967fbefaebdd5b3d55299cb3e11cb603f8d54eb3e881dd16d771fa39352993e76ca5cfb26dddd314a3dcf768edb5ff7856ffd9135e6625bd631e2dcad5548bcc9edec40cca9a2f128c6401a883388bde82279760fae6d517cef4683bfea3e759fbbb6553bdd57efc41b74dfa293ae1d6de3ee47f72df1bb7b626f77f74dba77f8cd81b90ecd7766e4778fe3b3ee49f7b47b963c45c7c12a9e76cf333ff3b220bdcac2709245599c257ec3d8b90ddff48edb6765cb7a02996dcbdc7231161b07696476b6165937cb24f21b3d88cea067be9d25e2776c67c856e7d83518f7db7bd149592feb67836ce8cea8883c6afc726dba525a9bd8c66e28ebb76b0e4eca5839eaafb0d7b8e12ec48cd41778f465cde91ab134f96cb8357049af80cfe785b3d8cb46599e56b3b1f5f3cc771da77b4dbf1a5decf6a6651397a6cdcbf88666541b1d60d73f3233ba33239db279b6c896887e7c9422e4e576329f99b1bcb2b58d966445b6c93eb38bac92991198d56c1f58cbcc5f6566cc640d632f98f1923583b9675764efe16bbca1ff96a6dfcc8ccc2efd2233333233ed9fdda0af1f55df75dc5eec57b70e5394da53c681f3afcc3df39d95182ece76adb1d427d74edbbd64653d529643e5f317afa57b8feded5a2fe354bbeb1be57808f58779c6d5ccc88fcc8cfecc8e2633eab276f09499df664fd0d6b6759ecd657bcce89cac93bd2603f3f996bdc7a6b533d30bd99ee880ccf45866466776981d65465665469e64a68732fbbb73b187bfd8abe57a94d67d7ba6777b9eac8b385df1b0f53bbee88ea7af7ac47af77634f44c597a612fea19f993f57b49ef3bffe25736309fdf3d5fc1fb6599d6fe2ad7bfac3197754f796f32ebcb34b0c7acd78dbabd4cf602f47af25cafdfdeeaa0335c94d3d0e3bd81e8f19ed1f93da3777a6684f5c6a5f6faf851e7daef7a66c4f7a6bd59cfe8fc9e91843d33b37aa68f7a6b8939f68ab09e9a51df3333b367f473cfe8e4f4103e18751ad78b6c392a320e740fdd0bcad8de8e4bb76ec431588e2d725da63cde311ee231ee97dbf5edcb7e2dccb7de40e48fd384b6542d27676c9ca9e164999d9f1f7ea357d539d930f2ad83348a2f766fd5fd2eebd564fda257ef357acd5eab67b473ef4a767af4ae7b37bddbde5defbef7d0b33b4b4ccbf51ebd453c882b3d333a7bcff16def257eeb75e249efd5c892ebde5bcfb47eefa3b7d7dbef1df44c6bf68e7ac7bd93de69efac77def7b3671ba3ef5bcfb30af9f1a8b6b52d67a31f98729b1e493fc2513f8cda6ea7c9b5917daf5bffe38b2e29f57a3f4a622b1bed6a623fee27fdb4dfed67e1c8cae37e0feb0ef4397e661f97d74776fd9536e467a5a40faeb1cfb8069dcd337856de5d8713e955e8f526f63534b9d66d65b25da337f5eef7077d33c2fb2323b3ed9af7c69f3b7f67cfc95fd746fd3cadf4c7feaa3fe94ffb6616f5cdc8f6ae4d3b2dfacbfe2a98f7d7a237dd4aeb81c40177a31c655dd237f2babf81d5f5299f56baf43f6535d7b67ddfcc06ab93fa668cf4cdace99bf1d2af9b7218dd62758af57bec67dfd4b3dfea67d98b29df65ffaa7fddbfe9dff6effaf7d151d6747be41a3646978cfc8ed531f1f3ce9eb93db173421701c0de8e6b9c43b47ba0df5c3b6ccf0d192ee911dab727327ffb0fb8da223fdcfac4b4342f2193dcdea469e9f74d99d31a87c1f37d3377fb66c4db1eb271ffc0e88cbebd5e24d6e4ec58e3a3f48d8cee9b91da37b2b26f5bd8b44edfe88fbe1d9176bf9549af7f287aa47fd43fee9b72f44fd1b267e219f6cf07fec0cc9041792da6acfb6adb38c920345734880789f9b4bdfdbcf54fb4d7777c94e04ed659ba9783eec0c8e3be9931835ed4fd72f6e177bae43b7fe43b5f8ecfc29f7292eb4cdac1b6b14ab2a31d7959b2b9a3c136ad415ffcb9c140facdbb6d7fb1fd07a67f0646470c72f135acef30180f2603f3ec6026f27f309791ed2cabce763d4975c8ce6cb1cfd978a08b099674b59d29b61d6dbfb9bd0fc626182ce0e799e70666d60c6c7e66560ecc4c1bd8b298993530f51ed8ba983e1fd4c40f1a98913f30bf1bd83630690f5a251d53dedb56d64b65bb89fe48a9fd9dce3ec47e2db776696dd5f4c32f069783abc1f5e06670ebaf06a607fa937032b81f3c64cfe9f5a0ed1d0f1e074f7d33576d29ac5d6af7c95a39357836cf9b12d9f5816c6aee9bd61bbc7a496c46dde04d2ca4c17bd6e9be8793e062f031580ff606fb83838119f103d3c3836319a5bd23f3db7ba32b52230f8cac1c9c04f3c8f6aaadf9d9e07ce81b7bf469e80d03bf188632ab6c8f0da3616c771f0e13d159c374d81d66c3deb0df3d8ddde8f53bc381e892e1d06fb8fdbfa6d587a361debf1b8e87268fe1d4c8bee71ddd51eef1a7e0ceaea7d81e1ece86f3e162b81cae329bcf7a5804723eb1565aa3fe598ca5ec8fecae236d7d94865848a6bcb69c9fd1d1f062686cf9617558cbb2613d9c78a7de62d8b07d66f71e436fca6f3bd8cb447f7145ff6cd8343afa63d88afb26bdcb7466d7a8ba07b6ff6cbf99ba5c89c4195a6b7433bcb1ed3ebc1dde0def65440f1f86ede1a3e804bbbee45652cf77db6aeb8fb0ed5c5cb0f4bdfd4d706574b8c967f824fe9df30bb1de64a3294353a6e18bfcdbce8aa1e9ebe1abe870f7fc9e3c1b98993e34636cf83efc181a5dd1bb0fdefa2bd36efb224d860732b6ed65748cacd318bf7b68a56d43ee9b761cbab3f5b592ce39f41b3bfe8829cdf04876fad91884b5d3ed7ea4e1b170af2e7b696d69ec5c76a5323264685bd1c882a1a9f5c8b4a2675a6f64e4f8c8fc766446f12832572cf26094c83af928953db9a3ae4406ede7c8b4e2c8d8c7a3bef8155c2b1819993732f26d6466dfc8c8b7d15874dc68329a8e66a3f9c8c89e915d6bb7cf19b9335a4b7ab6dca362b419f6c3ba4dc7e98e725ca814fbeabd8e3623c4aa18cffa4e26bafbbee82e2b6b6d7b8c4c5b8c767db63f1293dff55f76e38ad00f23336247e6bb9169ff5143765adad8d1a829bab55f17d9396ab5b77b8d21235d9de9ef5445f7f01a999935ba1a6dac1f30b4699bdf8d4c3f5bc96875c3c88cbc91f9f7c8cc8ed183c878ab03466decc079927d6edffa21a54bd79c76fc14ee7be3a74bf343dad7e992fdd2beb96399096e5f1dd6abd84fce320e64f6d87eb156e0c8f4c3c8dc1bd9991f8b056fd766ac5d3432e37c64ed95898c2b7b6f647e1bbfc2662aad6975dd1c71b11023ff466fc3d6c8f6b86dfd3dd18a2a1f5eb0f3023bfa46a54f37b20fccdcbd1c1d8e6c8f1ecb9c77dad88e64dbdaa7b29f76647a7774de1b8e9e8379eee75e6e74411ee65118e5719ee4e9609c77f32cefe57d6f959cfbab7c900ea3ab7c387830cf8df2dca6958ff3493e0d27b9d161f95c6654be103d68f79ce6cbec395fc97aba6dbd7c9d17b91905f18b5ff4447e77faa645f34fa75bdc1ed4fc222df24a5e7591e0779165db19b28d6d59fbdb3e637da9dcb4605ef71b79236fda588b3beb58c3fea16a49377cb75eb4eb8f509fd4109b32be9e975b9fca1be466e4e7976295bad1749ac4b63cb92d8319d5f98d8d88983a4d928b78667444eacb7b4e5af96d37f657d696b7fb15864646e677d1517e9f3f74d7f15b7a93bd644f793bb7918b439158f963fe943fe72f79473cedf4d6f4d36bfe96bbba4b8ccaad15591f22dac6f8649c7cf5dbbeec4d285bada54fb79fc1e49f9776feb87d713656d6d9d1e99a8ee91fbb729cc867b90c6eb6bcc8f74e3fd95913cb18756b336696e57bf97e7e2063d4fa55b9a97b6ec66d7e9ccf4783e8e8cb79a0bd2feb23d72287f313d8e5af28356a9397a3a23b570e7bd2ce61ce65b797f60c330d9ad1ed36ef8a5d9b9bb4c7fed81b9bd13ab6bac6c8f971243ecad8d46a9cc8bc1f9bb2d81a0d17928fdb4962eee5fb2203aca535ee8a1c55dd603ec71974a1d167e39ec4bdc67d919fba5716f67a7e3b1e8c87e3d138472ba3bedc9162659a2dbfad979de53d5b56a3cbc613898d7d91dde5787cb5f4fdaffc91b27d5cd2e9e369bcb13bf86d3dacdd3f9e89ac1dcfc56fb2ed6b63855697f54c2f8f6dccc8f4c778d956bfd2ee574bcce7d88ceec0e88ab19199e342f61cd874c71b91c1e34fc860d3dee30bb49bf9ed187edeb826e3a2bc5feda73360f7fa6175f6ebe5f4c7eef3dfc51477d6adf45efbebf7e33a74cf09a4f9a1440e9c0ef2f179b0d54de38648beb11d37769792b9c697f4a99d1eb16bc1c7c62635a98dafc6d7e39b30b6769eec6d2dd9955f6a58fafe4166829b05d7b42bf1bdb1dfb95b707c9bc7e3224dc6a657c766fe8e1f249661479d3d11356e8f1f6d34d1dac256ffd8796fe7b9b598c6b6e6cf18c176b4d8f4ece76b5e1ddbdf4eddb98b8eff61e4e5c0d8999bb43286b7e89eb523676fbc3f3e181f8e8f82f9d8ee14e17edbd6f8647c3a3e1bdb673fa55e3a43ce45f3dbb32256bf4efc8937b17e903d1d7cefd6c20b5ddf30ad6ced5c3b6bac7f3009fd55b2fcc9f98eb23fd246eca92d7b63fd4a30ef9b5eebdd4e221bef91f59ba86d2d9d492c52683c175d674757de99249374d29d642863cf5a1493bef515f355af3919e44fe32bb13cec3a85b5446c3ab61d27c3c9c8f517fad1adf9d8f21f06977938d89be4a343d71f1e2cbcfd926edd9d21dfe9909f7d3e61cf3574c464fc8be7bfe4f1f5775f74bdf97e32810d60eedbfecb758f369e7fd8de57fd732ad7f86132b5d6b3f5bf26b3f071328f8e260bf5474ccf4ecc68cd8c3c9f187933312d39294a73f41732e08b9dfed1fe71addab680193d93cfc9c5c4e6539dd4267599e3d65a703626ce6d4c1ab043fdd2dc3f43cf99cf8919411333c727978885999e9b9834268c55d833ed66c64ccc28b0114a966762f29898993931336ef2108cf4bc3ad61fa27cd2eed911f3d8fe21a6e564911d794f62abdb9892d3453bebce13338327d61a32bab8d7125bd77a84dfae7decfa23dcc3cab508db4bb63caf6d8d01d9a8c6e4cd8e7a911cbaf7f84474c0c4b6f387ac37f57d597718ec61cdfb1db123e8442743f785277bdb76d2fbf67b737f7280f58f7db4cb838cb8727fff6a4ce8f58c586059e697f636a86efa6e9cd9b63ffcfe7bdee3de6b8da361557372d4d6b89a1b0747dfe826db6e76ec99769c9c8a9f6dfdd9891d6fe677a377f7ae56dfef4cbd69303533646a2c99a991315363cd4c53a4465fe414adf4bed511ce5e7cdf99d3bb357d109d31ed4eb3683ded656df1d2b315f63d754446aa6c413af969d47672e045f64345cf62878726bfa037ed4f07dee774181d4d47c1dc9e699fe6e61a1b9e0c5be955300fb013c2eaa1e9d46f4c67c3d674ee776cfcc61ff16c8aefde8fe285d3c57419dc59399b64c8d794636a46e4743d2da6e6997e6ef7ddfa6e5fae7ba760056b45cde9e7f4625a999a5139adc91ea5a99102d346ba9c364be7477ee68f5cfb1db78f016bbcc3cf7c386dd97247ede9655b6247a6d7a7575123b575b91e35eda89f9a724cedec37b3717a37bd8f6e8cdf76ddbbebbf4e1fac8fc23394d1de56d7dbe82bfb523ea7a5fdccd28ff61939cb69f27fa45d602d18ec8d2efb077f4467bcc3aff826d6c534a64f18edfe8ff7b73364e7f71867eea4c3e9f679ab3f5c9460c7af9c1c71dc96c699cdfb59c6d7f465da99bec66fd3b7c1d9d47eff31dd9b6ed2027a04711ecfa43c352d3435f263caf8c1c376aebbb9fab295294e363cff4686d83db2b1ac1859bb797a84124fe49ec6c3fdb6da93b655a6c75b1fc8f90376449c88976acf91db75d8a9add919d67e2193edbaf1d4f6fe93f83d3393eecce89b5910d6273ccbd0dcea107796cf9461164e7b337b96b08328a52fb265168bde98e18c9aee61e685b5e9280f4633538659576279339346daf983fe082fbc8365d64384f344dad77ecefab2463033759f0da57c6c5feba7cc6ccccfea1a339367795bf70ed8116ffd17ee5956d90a9d61a3ae724a602beb13f81d2eff0efafbb9247f9fb63ae00fe9919ff8b1e5516efb7c3696cfefd6eabff821fcbebd538e529a3a6bec787d954f893e976297e6f733330e67c63fcd53ec3fbb9335fcbe797666df49f022eb23c1dcc8b162665a72b6982d474170385b41239f5306e10c1e668df3376cab3dff5e86b8d960e7aa8d5216b3b5fddec5441e3012f6709d62ae97f4508efdb6f6deacb0dab0f7305cd998b7bf1abdf9c3feaa3feecec2d16c9375669f7ec3c670ecfeaed985bfca3e6695998d9af666b5dec5e07e564fd799db371bcc67b69506d005764da365be6bce5a36fee156baacaeb2d1eebdf4313987cee1790a9ecf6ffbb23fd75ed69a5c78c17433bb1c9c798bd915f6122d4b670c7fe68fdc886eb265ef2f8c061cceaec70fdc851fb5ad3799af6637b3dbd9dde8507ca3e07c766f634fd65ab5bacffa0c363a3b7b907fd39f747b92cfd15f7654f8c19d9b254fd415939193d3c62610a9b56d7ff73b9c207067354b52affcdcaffbff2733636706508ffc546794fd90a7d2f7bb7e09d3a66f75007f8efef5f95642b8fba762b9ceda76b5c11f3adfbc62df8fe3d652acbf097f84e7fcac2d3b333a65f62473afbc6f89ba64774df5a7fb744a25b73ac2ca325b2aab0b6c69ad7d3c3072636666dacce43deb94ece1f36d4da9b3acbf327b95f799fc70de9b7124bcdbc4c6c4dc1e2f93dfec4de23c767d99e7aa7f5807c73e9f99f9cdec43f2b3f190d9de6cdfed2f58949ee31edcf2faec6be91ecae1cab59bd72fd647ac1eec87a26bdddb244e4477da585eb496b58cd981b0b37eee6687b9a9e7ec4874c6ec78b4999d88df36434cc7ed12c18850195cf6037cf4c747c926f8101daea3ed05ed6f75d9d93723fcaf5ed023badeb1bbc7e1573aa9a4d3766788f581edeae3ec5c2242737feed9757db7de728ed8d6838cf7818d0f5a3b81fbb55ecb673c759dfd462c977920a74ee761dbc50068eb59af6d901a7533c3cec43bd101aa070eca312d5c28f93c46e9edccf89c4c6d8c649e6445af314fe7dd7916199b7adec37cf7b7739c7e8ff50fec77f3fef4cded566c39d9ecf62ff57bee2c5ae1bfca9af4e0117132bbc6f3ee453d2313b24b2ba3bba7767d55cf2b4f455e58fd29a3dfefcc077e311fce47d68fb196e63c9f8f23b7e30fe7b1edefaeb67b4983a9d3017226aeb4dfcdea88f9c4c5d91aba67b5bce65ed9f147cc6f527f3e9dcfe6732b9dac0f61dbd5591fa62e79c3946be1af86175e61e380b66dec3ad17c395fcdd7f3626e46c3fc737e31afccab56ffcc6ba23be675aea770b41b9d7eb4d501f2b68b69fb4b9f7deccaf3ed2cb3ebea368af2a3eed819c13f7cfeda5fb5d268326e8bae7a6eff38e277d21b718dfde3eb38d3f7e1d815e16534cf0fbaad79c36fcc9bbde6bc35bfb433c6452faaa23be657f96a7e3dbfb1fb8fed2ec9f9ad1fcfef5c9fc978c27ebbd2fa886d75fb4bdbca762e7b628f3bbbd7ae619a916cdf3735b77b75cdc899cfe49cf5fc49f6cd58cfd8c640ecefe6cfd064c7d2132e467d20f1f7f98ba437efc8de9fe98becb7b1eb1ebaae7252d229bec8469bbf3b63585ec7663c8bfb3d4f249ee5f6efd85a5b3b74d2d6bdca2a1b1ebfc6b5beece5b1ab9c83782fb3657cfb853ff1ef5c4c03ef88b4e5b0d7fcbdadfbd9e61f7256d2ad539c49d4c4c6fc9c0cdc43ffec4b64d2bef325ec87f5b969abb99dcd66e4cf4ddbcc4f4aedc775809db56ceed6b47d62dbdbeec3d5b5ec93ef9fffb7beffc9735627da7eb775b29fa1bf8da169bf63f4ff90ce213cf363c43a312e2d5ba960ef5b8b746ec797952a75ecd732ff9e9fcb5e8485dd4563f4eac28ccf45207b00adae777b13d0f7a661bfe93ff737cf22df5bc48b647c1c9fa5cbfe7291e673bb00b7c8f2380f8777a19911a629fbf1647ce8d58d933df482eed962b4c887fdc57831091f2783d151d8b76b10612fcf17d3ac981c8461f438991a07671eb426d3a035bccbc3ac08a3c562b1342ed22ab85cacb362fcb4b0ebec7178bfd82c3e179b301ade4d4fa6d6951a3957cafcdefc7b3a7f595c04d5eea91f2c2ab3869f2daa8ba41ff8f1a2e67717f5c45f34fc9ed10dc345737ebd6865c5e27271b5b0b5be59dccede7c2f3ef72f1677899f98e7ba9191dfd12259dcdb7a1b1b34f13df35bcf7cc67e6ad2ac9aef1fccd0795c3c2597e63bf3bd79eecf7f06fe6d5237ff7e5ebc2c3aa6ecafe6df6fe67a5f7c24f545129f9b7a8d177b0b334216d9e2607118dd2dae17478be3ac085a8b22baec0f1627be973e79c9629285836e783d3b5c9c2ece06e3fef9e27ce92fbdec7e512c0353ef6369efc5ccb4ef8c9fb61d83cb65b8e5e9937dcef6c732faf1f9bff773fa346df7a692ff647f7867f3b5ef41b3e5306364b434e362190fefecfde9097f67fb1fe99876983e4d4683c3697b99ccd661649e4f4d7dbb66865f0607cbcce8d9ebd960b6b7ec1953bc1f1f2c07c9c9e2697cec45f1ebe42a3e35be696f395c8e867dafbdccf3e672bc9cc4f7fe831f2fa78bc4f6bfe91fd3ffe313d3573a0edca7b9a047da5bf966e7ce7226bec9c2ccc1e55cd615acafbfc4bb97dc5e5ff830f65ada9540231317669e2e57d82181f5e0d1fe560658bbd9dabf5cefe09ecfe57a592c3722d3969f78fe4c3e9d0e32d7f2c25cb66c90ffee4c1ded7d9c5b737b90c2b6eef7b1bb2996b5b033b3ebcb368dba9c0fd773118c2fedfa09e5fda07f5587301686f7c24c3f652dcadde3be64d32e0b53a6a5f5e9ccb56c623dc393b3318b91d4d1be5f725a601f5a5764a75dffb03a98eb18aeedcedb5fd695d89edcfbc0371e595e865fdbfb9ff8a4ce608c943606cbc7f53167fd95bee773cb96fc6e79293ac4ead28ce7208dcd927c8ace585e0523bb57245dc9194bbbd76269d2581a1d66638edcbf4e7f56639495527f7cab4710a759b9f32078efd2b0216ff7b42b56de59d65d1a0dd94dfced3bf35edd730dbb47ca1bfb8da5dd1f3c4b8bfedde06a1289d7e96261a75b7bd4d5d82bd9bfafb2e7b3070decae9bf63672076fdfc6badddaf04c76cbd87304f6ddbc7ab6ac16ccdd7b3ceefc6264f7397590beb1bb6dec67791f35968697a635968fcba791f16796cfcee694f7bf6fdf27dcc03ed9c29d25dcb833f11d5d47ffb357db97f70adade7af1926567f96adf0b63f2f0dc1eaf7b777eb2331e2f5f97f60dac67cb77279d6c9cab63ca6afdb85e30f7726fb1dc1f27cb03b1c8ec0cb23e1ecf71587fc1ed5279d8c622759fd9e9d7cbd9efd7b2b6bc7bef9fb86c19ecfa8addefa55104f43323398c33fd701d6037a5ddf36ba473af9dc56e1ce4a66d8c95b5b4abae2f720e24be30fd65f7661c64ddde265fd975a2e5f1f26479eaaf701e7385f39bfc1b02d24775e75b7aa5f7057c779efda3bd3ddf762db6fff24cbc603b07ddde95f2bed4d299697db71fce372ccfc54e2cefcdd418d82362253ca7f1b0f5d0ac5dc958cc17cfad2d2dd8bd59f97607caca937dbf2a03dee40a9c11077bf541e498f37e63d8af764dbadb7d747bbb8ee4375fce3e972ffa38dfddfb77ae4aa99ca6ad56466eaf2279d789f547d447aa8aae5ec5b2877a9588ae18f36d412772767f95a23daeb03b1df6b89d2d5ff62c97d63bd4f33efb9117b39fc48ffee68b33c5bda969c7b3576f9bfbb6be598b9fd7646f85dd3fb6eab6bfbe0f8c3e26fc6aab435699c400edba9cf59bf55c3fe3a0b415cafe6679ff9c5ed8f72b73aa22670b8d4cbe3576dad370d43db57b8fe2e770e4f6415a79e57a14ef1eb1f3f245ce27381df4e8ce4337ecfc5ef5567dbb276b5edbc62a9cccb89a8c54b7b855a9ed3972591bfd3e4ee25ad64687cd4858d9d3417babe1788a73662d1b430ae656060c2e8337ebb9329e6e5b7d35dab28d68aff2d5d8ee4674e7dbdfbe795779c59eeb737127fb1ec9bfe77db24647d9bd5ce9663559deaca62bab13dbbee7cacd5350ebb65bf99ccda2a3d57cd25f2d56cbf9e36a65f732dbb321f68480b562ed6871eb45ce5a95bd073666e5eaf7107dddcff4f0e3bebaf2a8b5eb23ba77e2fd1ffa7c91f2d112dcddefe5d6b8b9c3fd071d289fb6ced6c24c6f930b6f62fae4c897773dd660ff3c3a9deff674db3dcf2bbb13c993347b8746077767896de7a4865824dfb552515d62d3f2be7bc717f4c8754987bcae0a1b275e6ddadbb8cf71fbebbed4f219876bd141ee3c34623856ef0c1e569fab8b922e799788a2935b5ca17ad9eea329bffbf0073df28e5d14a7b0bbb18fa86766e1aa22efc0b5f9aeacfcc0085ad5657f17d3ed47c8d76af56ee84ef3ba3abc96e4fd6e1caaf9cdbd3f19d7b2b670909b72d9f298b65d35e59d62e5772d5a89349ac8c9b5fe427c3c2b33ed2e98d160d5b2fbc6ec3b469cc582758cf27ad20fe7f079710de1e12bbbd179f20feb9027e46b75a4a9ef4a67c9b68fe93ffd4a07d933aaab6b9c6367ffd4da5fde87a2b149c4feac54b57b2decb990d54dfbebfe8aefde359cb6bfb105709ebdc1f55ecf3732d4beb74fdedd27fe4705fb519b784f0663fc559fef8eed94cecf35ecbed5c4dc5b19ff62654feb9c96de25723599aa2cd15520deffeabf3042b9badf6a61b787ec436425cf72ac1ef26152f18b553beb8eec68f1a3b65d9b5f3dae9e448789aeb272977b95c6e1aab27a1e1fb97a528f94ff766dbbf4fddff04ef260393e58d9f3eed9aab37a9d4e57f694dabd17b9fce55d2dee9d20ab77a3bb5ac3faf0349cac3e96efe673b4f2567babfdd54170ccf527539f52fb717789db69f1cbf5891ff73b85fb76bfd63fa843ec2c3f0cee6c5fad8e56c733ec3891dd2fdbb57ab73ef25ed21d5fd231f535f6c3bcba3a599d7aab95dd55daee9eaecef1b708f8774b5acea628ecb99b35def3bff6fccef4d43b72ef9face26fc2ac314eb7efb497bf6375e3fec65af1133df22b19f8dd7b06cbb676f9bd45e5eb45cea2db13508c83db91ce5d073fdb95409de1e48791716b2337d621e2ea3bfb765cfc7ccf7ae26d17d758476d7de73b9f2bef76e33b3c86d375bc36d6dbda9ef01db575bf9abe0b70f74cfa5fbc6c2ccbae3bd9bf8fb236f2706d46f3ba676422d768ae65af5c62da6add97b5e1a9912e8b965818367665576ddd3beacba3ffbbb5687c9f60ad9e7b6275bf5d593effa7fc11eb3fd97707d8ba0fd03fa5f5f16057b7ec5cd6afb2d19bf5d05c23899daef36fc622c6a3f589ed2ab2dda7b71e97c6e977e3b96c1b95f7cf699afa5e14bec384b1229ead586bdce7abddfe5dfc06efeee3fbc7e327bfb19ecc47eba9d4d0eeee0efdf5eceb5aebcefe1b6ad653d129c1d57abe5e64954477aa71ef265aef4ad6a5d7c6b35dafc2d17a2d79592bc48d127fbbb7d8ae3e592fd7cae2856d651b45ad1b59be11dd27ebe8edc5173952fe7b7e7ff6d3f86b9e19216ba3f3d626fff5859cfb9b75b3deba9275d28f60beaeae6b569ad835605b1fbb93c24519ec0aeec356a7feb8ef69a7fdd84ed81deedeb4906ddb7577368507b27fee9fd325b20a3048d7f57543fe8252e8f6917ddd933b7d6aff5ce7b1af717a3c6e66857d0bfac4ee86cd313e9bbefc1d4a77fed39ebc36eddc5cf4d72d7eb7f37e94f2beb9edfe875fbd37befceec5f299b8eaee9cfac9557e3738edf9b6c8e5f5254e4dd93d40a675d6bb67ce4ab246f77de19c82931d26adf5cd8e5ff1c4198359627588ddd1725192511fa2d519e3b2e9db91e7fc9fa1d8a96b236ff2bbf6d73592f64fe4d35fb8522feadaf7c2d873e9eb7bc9d7e69f9e88bf61cff8bbbf8be26d756e794dfc877dafa5ef5cec6ae75c9eeae1b27f421f7067264df64bdffd039f36fff5c3babd7e94f8627eb6ed0fc6366d1ffeeafc885e0fb2c7796deab97ec6787bfd46475ccb7b78ac3fe7d6c276f7e77dd74ff6fbeffec6f0f67dbf3fd30be573d9dc67b4867cc5fcd4b3bf120b92b505fbfc87df59bfac3bebd7f5dbfa1d27801fd61fdbbd9a3fd121e7d21a7cbbcc285befadb10796e717f8b73f68b5857e1edb78967db70acf0dac0f204fed4cc30e36fb66212bc3e7d7e1647d349dad8fa3a3c4daaf27a57750eeeaccbffaee7c93763e307ab56d63fad1d1f4757dda1f87a3a8919df6fdde9d3d412be7692279bf17ac511be7d35341eff6344112bbbdb93a024bb141b6236357d8e75696c9e5b50abe85c1eed7fadb7729ee5c6ee592fb6e6dfecf3887cef347653df24d5974ffd84b70b7b6d2f0bcd728fc609e3ac9fc839e70ef2788edbb80cd9871ef862bbfff7857e794fffec8f2b77f7fa4baf3f99d5ff2b3fb5c2b29bd6784ffb67f03a4b0ab5d46c61701f448fb272d5a6e219e5b3123bc3069d8d9411d63cf22ba1de367a5a8b12feb097a26cdfa22fbb2d66ecf5b1411dec93894f559bb37c0fed585d5aebedc5d13f93b7c92135c6d792f7b11cbf99785edf1f5f6bd5eceee2ef94f5fecf69fe9de87afeda97e072d52eca5559d827387dcfbf08ffb231f523f1b81b7f9db98dcee99c41fa238edafbf9fe02c93fdbdddbf56d81380a1585be5b527ed43c6afaeb12f63d7efd8d51ffcfcb93fb2fb1ea8257cfff2f7d59dabf9e5f9ed1af5f6ddb5f29e40630f16693829ba8bb3c29d5c2a7a7ae670c76efd628fbe94ec6b9ea5e0fabb7d2bd1a8e8dbb314fdaaf82dd6e6b6766f8473cb3c87626749312886c5689e8e7c6f51189d61f7061463efaeb032392ea6bd97c5937feee3ef33aafef8d1fffab39f128bef488bdb732d5e50cc96effdf5bc657bdcc5d9e618cd9de8cb79fa7e54d211e591573e476175ee39628290d5c93e58d7494ae7f53012650d7b32fafa4e93bfdf1f717b256cffbdd8185712ef9eff70e78618ebfa690c0ef5347d5fcc83f9f8322dfaefc5a29b489b96fa49faed3a98f7faf6fda1edc5b76740b7efd4dff671f9efc1fca8477e36bf7855bfb9be7b8edff19db3909fd6e68e27abcfc2c8ee62d5feb2b6fe831dbb73b175dd0e6aab7103796792db0360d22a8c1c2e70f67e803dacc546648e5d632d3e8b8bf1ad3de1da767fa9c1b59ab90a53cec2d4a330e59efeec7dbb7fa71e698b4c8b0645dd9e99b67b538b86c8723b1b66d0893c7bc9730ee57d4e3ff826ef5f6386fa9eaa9b9d75a6f7ad0ed9dd37f59f5a67b752cc5ebbef7274e5b82af9a13b6bec22f1a0535f25565598f155b4b6edbadb4fba3faed296d5d9dff9d4eceb74876baa476a5fe6d28fefaaddd521bbbaa42c73656e16f6fc967946f63a195db23cf31b53e327b8774f2cb0ff665777bc977400d78c3f648dbdb8945dd1c555713dbe995f67cf9e7bf7888d83db952917f37910bde17ac3edf18ada83c3f587953d767d7a9da595f8c597f7ef5d7a83ec7af696568b9be2b6b82b8c27adefe9dd95257f7d8d5dce1a9a116adfd9523c743fec0ecbf4dcc870affd250ea556d67efbcbd90f3d53f325962511e1a22d116267853c6645017fad2ccbdd1b9d2af36892664518b4d59a0dffbff6feaba975a6690385cff7cff87cae2287da474eb2c12c4004033e9373c63955edfffecd35dd2d8dc632782d8c59ef7aeea2a684654b1a4de8dc579fa8cf27e27fb2f3412a9bb1707ee7c85824c8bf0f2aec59947128f37d1fd30fc977014e8ee2f7e30662f61295c513e7e8986b1532cd92e59902afc5a9a187989898d17a91ee167ce4335af8510c6c1ccd357e8f38aac53369d49aab8abcfc1b7448f39037d200174a37598017bcf6960b756ea1467071e045722485b6ea95a068f4e290f25e16475eb46e4a9afc171bfd3cbb6812fb8556223ad7be250b34fa1b6097b13f07b61b5d67eb35e4b9813e51220a000c29e45d003f0b188b8b63c2235c481ebb7814d92f84d8ed851aff05f8938c25f0017cf23b74388337d083f8fb052c27c3c5c5e272e92c13c4d7b7ce63ffacc94ee12c3dd19bfa6c5de8b1cd0d9fc11bb52df090e66de92fcbbf53fbf7d3b6a91eccdeeab337477307e8669d93d19cf808db64b6a1518f5e94c69e93269e58f5ef97956575a9f8ccb23e6b2f1b1c497f497e10587ae14f81cd68d95cb6de6bd5c2b23daa2d14bd98209251c70f3096bc67d4aad8fdfbd351f54363ef979c62e23d315b76140d7708070ab8b7da1a5125bd6ad95df6967dfaacf5068769ec2b4965c02c435cf0f21df8ef4e77a9c66339acbc2f4794a3283a9ad6ce6f96e379be9b47ccd760bad49899824db09cce52c0c7edea982a8e4e31a24a97b3515147ae3bb63eb343bd45cdef72ce91ef97225d553ce4516a4c173def4a2648719538259754fa8df258d7aff7266bfaf19f1c6dfc65e3fb3dd5d53d23bc278cf47211b53d6d6d7934e457ecaea5da01d343f25d036d1bf6a9b1da19cb154b2997cc4380b7d5210c62d439590a3696992762d3935dbf7f9a79c905f154f88181bbb14c31ed649eb14cd37b21a374a9fab7645e11f010c648111ffad2a5b1c5fbf4789c13eab7cb1cf38a22496dc04a411f205122bf46d36cec9e33c26a7e2f1bfa80a1f3e0b9c8dd08f485831df2106b6e75ae6121aaaf80ca013d095455e7aa1e7b81beb1440c02e7deec648e4c7d649d8f7c270fc1d1234ba7ceaa74285e8b109545defd84d698181c684ffe2d667e79354800cb6a79ddb900aaf1b2d0a9751acb9be52f8eb057cf5bde2eef902dd61f9507d349bda8b115b34eb13ce7ba1305434e95bae5bb7e7fc4626512fefbb073bdbc6fddf66eea374b0ffac164ac33559f5b33ec8ce5c3f271895da07dc4eaf368f93ceb3a3354b4d1e8e48c638b6be0efe91d4ddf9645f8a38065ac66f392b058eacbcec5f285f53158314e66a7cb57fdbec9e51bc54d97d987ff5e6c679725cedb61fc32338e4eb00c44178afaea77c34b96a05c1213ac737f28be4e57d3cb912ef9de18df00715dcfd7d4197731df47b5e4f2b83c88c52ffb135ebf7d3dc4ef68698a9f815d627962c46b3d867ac6474ddbd38d5d82cf4b255b2fcfc87685bc3d60d4c3ba0c9abc64da8bb8a7ce0bd1ef20af50f20c4c3bfa77f00eb3a915bcbce0fea4280f025968c80104dac5529d5f395c4b04f9fdeabd5609ca1d0122c1caa75805e820e227420635f24cf06e01d63937c4c6aeca8ccf7b4ef8043206c0b2ed30ee098ed89de803ee8b710d10dc04a3e4c0f0fd5f7ab1715f3be123871c8123b6ad22f18ec198ea290798caf06d9d53cdb2c685b7bbfaec3fab8f649cc5aad24f2302a47c3e196357686d2ce21dfb441f1169ab441207fc09ab2afcd3156f555bd5578dce01b0a5a07b089efd0a28701d67ac6d6ca81b78c678178aa656951c1fd40b2c04b904dfa38f00e3319758e8b85d96e99b73e849fd2a6aa5b41f1c5763b69ce95ccf05ea406277ac5a4e717abe6a43425c75bc008b173c45e754e21dbbcbe74aa1d9981e7613ef437fdc551463d553ad3fcdc1d6a5fd4c6ad7adde576dbc6fe2bd9e6c56bca00640e7543df28068f76a60485b8fe4d30f72012f19a76bc73c44e675350ceb8ae8f97ea5a84e50166da73ae0f951e3d9bc5c8d9a17f03381a2a879fdbfaf8fb07fa5dc261feb6a6c44177ce443dea08fe8e32bfb012ed80fc2b8c0d062250f1a3c66257e5889eb113fbaf4ebc40bea7105b4e43b6c5b881fba32e4fa22c50abc97016ac1cf2dd16f578c1fb6526335032598132fd43c48f185d582ea05a296e44ad1dd15764592f432e0e7c3b3ba4a91ed0f7c4747afa89db5e218e3a17ad62a435a3f227de01f814d0b3c44f252223e988390b60791423be421180fd4245e2122e7d40b700e747d15f4f995c7c6f3024cb595cb3c7797fcff67f5911745bf141d874fbcf232d458ba2461d9f15a9fe8236f952836a068e625b291ad72b4fa707e8c4caf31e705487e0cfaf2ea90ce5177c87e6ed6fe306d50bb7cff0cdebf3cd031afbcc27484feafa50b1ea173da291f72b1523b67754578f489413db5423dc066f50e1e536042b56bab6be82cd581e3f64f156daff378700428fc2d628732636bf1bb95e223e545b9b7ba616fabb68e0f757ea01e4fe8230635828f5f7203bfd3170fc48afa2dea62a20688dab58a2aac7e398b9ef6fe490d4b6fa2733fd26a8c6e413d1c8d03b053dbe3cfe9232cf72f5ec94ebfba33f88191a3f861f32c3e1213d723b69ff7e7d5fdf2da5baf5bbea9ed08fbe4c3f7874ee1197e07b512560f5c433865e073e4289e2bd0934033d5f880f7c1ea091cb3f63bb005564fab67aad514c465199896413c94c4f71e537ea6e00dac8a5e50836a22988cb6446b8fbf35de5f694229305fa889857168962a8d9e9ab715f34c5493d53c5efc4aa24f9e13cfac5d1abc6517f3f4b3fa08f2889504d1bd812fd8bfd29afa1acafd16726b44ea121e13ad65e41756afabb7c42471c31889052b579d730d2755c6c8d8854de4b363c959546bf5c6b84d7e0ed890743df76ae7b18b7ac573d44d7774adc27ac999d52069951295d541a2b33a74ba9573e004a8f7bb5e1dad8e9b6dd4f15b9dac4ea758dd8ee030abf100ef28fab73348b28390e76a1de864d0688e094364a5f4b3f2015dd75e4cc66b3ef6dff27f6c3b7feb47eab7d283cecb3d5f499035e4fecc1227ab0baa2ab8c22eb87538f6cf9b24755d17ff155562e715eddb5aec4c7ffc79ff08fbb351776a5a67b99769df6f638fcbce92cf06fd83269f4c948b0db52b93c87b169cc5b8380013a3f1bbf9488972eea12321de2c59c68a57c70ad1f6a4a25f0df57d7f48fc7606daaa5649b266f43f4d3913d55b3a57cf53cda5c931e7e778acf5428ae5bc8cc06608cc6275af649d9e9384dd8af50c78ef62c7f99338ba2f37e649d085928a472694c4976cd17b26db54636bc6b10f62b74b760863b1c9586a71b15a5f9aa79fd347ce880e366f56ed6417b6f85a9530d195bc1b892bfae4c833a76b15bd195a3fc7b66aba8891ec35ca24c3aa4658bc6b31bc08400ef8c837bfbf46273a70dc641f96d6f9db2a937c4f2a4d3a396c7b8b57a7981c55d3dd036736ee038316d246b301fb542f5ff59b3784673c85fdedae511e6a0fa83f56fca6981cb7a7c9c9f2daaff8478de270f85e4e4e7525bc02f9e47b8c92f19e55e37c4975ff9233d49e657f8bd633cc7cf6981db16b9fba79e4ba32b07726e7cdf7245005a7cea2d64f2e93eafd93c9baae9f8ef880ce93b348aa159b04a56df7ddee1161d770bcd6ff757d24cd7b3e47347338e2bcf24b2fb0956c4d7b36f091aaa03f9f5175cd0886a39d9f6ee64a9a9fbf918f24990fa01eb0f616de914f074873c8fc820d071e565d4f12f43e4b988c669d45adb31878c1824f0fad1f7e02f09f2478b2e345b0f6033d459d4fe6a8495d113d070f31e31bc7bbbfa9e95dcc7100627bac7609b312b63d8de17c403a0be2a5e11d85bfc48ceddd49fb597da44098ebc052ac979279d4e61bd66c4be216b4c78a7995cfa4dbf8b788e15a1cf7f3fd5bf23d3b73c69db4e54e9b8f7c872dcb3cbed0739257ce0c7891a8d6895a6189d7c110fa8348435211c06f3b45d4c0d5381f197f5c5e906daee1328e5446e34b516c755ee353fe9a2ae92a790d6b6e74bc0413b37cae9ef362f8b21fc5f7311f7dcc33ecb66b9e823e8cfaa8680a0cff6441bfe3b8dea927910557adb75e6be3c46cfada4d246f92bf2a57e56eb5a3784d86b17abc1dcdd3cfeb239253fc4a769b59977cbf5ae2facc5662d332b171f175413cf019c5bd6a7a74e685787ca5284f8bd4bbdd873ec2ef8f98db1ec75b95196fcacf7b816d4f7cd9c95bb25c6b4cb314f7ff998e5a6a135fc1b317e6e0e588a7203a3e620394f112de227aca8077a3993f62da0a9fc2f1dd877e92bca33833bc8f7e479639c04f92f78b4943ad9d86e820cf216f951a62bbe2f73fa88f3cb33ea038662bedfc028e54d2a3e8ef966ff1880db486242c432f613c5fec101d497dc43b64091a83d154cf7be6e78b8c69b49deb2331726c7054b431f930be4185212de1307e607be15f493d10a92e878c567cdfbdf167c3f3fabcd6776609d5e01ba80f928f4920402b9a8b9abd1ae7f610df118e63f2d9a22c26cf7d032a1ffb4b9e041b13b6b079697d9c0dcc925889eb776d5bf6f7eb54b0fb40f5265be9a01e8c1ab7fa6406fe591ad592451d7fe06abb24f827a4f485e6a5bbb14dfeb83e12c9cda8d3671dc50d146ca9d964626398f9d86fb40b922f5e185587ef5fbca01a19ae4bbe7a512cd7cff2f277d5ec5c4da16f465c31f2301bbfd8e6f4e80558eab134fc5e902e285f2239241e51bf21bf00ea6724d56f3b39c23c06a22b7854e28978aa543ba54cdd90475165662f92b7833c95ca43f85cc17c8cf857e27887e52f096c93717e9452f87d80e152328e6f145f37169c33c15be498de72ff9bd7672a9ca71fd447d2c65e05f6c403f0e65bafc992a211c5f7026c3158e9c98330bb26a8b7c83b04f416769ae421d964e697e4634870551b1f35c995bcae694bcaa8659b661bba997b9633fc23bb78bf57c60094f7541a37d7d573b5def04c56ef8a6065f10ad69824360f7d249b9460c2248f66ed41a9dc4b1e0ffafe39dd03e3957c4e9e244ffb8f0de4663a8e8b5c1344e6086a50404d044fd9f1b8dab441e3f5b9d15cae099017c45668c63698fd7b8bfb2cef56f136d65a7e0cfd36da3669dc77f100cb83e2b767141301ab8b3f699c4f406da6dfbc3eff0e7dc4a4dd4ddab3902d81833e2c1818f3a5b04268a42e3c327cce8916ebaac06d5878d996734e1ea7ee8917e6697c17cfd8f63d25ef9065e8f98c6c571144eab3183e62d166c4a1758b8882279f3a2a616b5be009c5c40209097e11d8b3e04f08fc4e252fa2b7e9dd8638b66668d3125d2e796949556f5ebcff294e4f8ce1156bfa6529e65efc596751bd918fa4794eb6aa24c7170432c12e6d579fc9033fa78f44f386b15717a81fd229d64f666aa6fb1215fd2678bf5eb4e202bc4ce5fa6d62d57ceee79d623d9f725209a577f494ac3e2044b7943fbea9698e19e42f7fd8af401fd9c5fb092693f025fdd91f63d43b4fce6c3e6b15dee1a97be69ab6fc9ec0488ccdc7901ac60e614beadc0ecd83484f10cc626db342e4e27daaac63c17c8af1b525198c654af19ee67836d7190ad821cf749fd17baada3f17dba0ec10b6b5993cc5ec9fadc56fd322fa66b84345b71ca8d599aa19750881cba3debb76ba23ffc7dfad8f98f415da34f057b95689c628545248aace91df975e68cf971d7240b517bbc75ee82f60dfb3b6915f504edffbd48be71bdf95a31ef78e668e0aeb28a8f38b3fedd736e2d3b0ca0543df5e5192f3a7a51fbe4eefaa63635ccec3959e6a2c2e524d8edf7ab276c913f95d509765a6f8cc50d1ee548baf3fa0bcd088de21f15e81c7d6e225256ff32eb1be0b788b956d6d361d818fac00a9b322f56fa47671e91be62aaefdac3e920bf6a6abf988d21f46aa3937f5362c7a58ddcb29cbcce7511c58b4543b314b753cc2ad3f74dcd9a5b67f503c96e72caa4f959314761a72300a8a7e4f1d3396773d3674d7fac8d4d04570843ee251dc958ed69b7a84fb751f62ef6a9d43e923211f09696c8df58620e3f829f4920a7ea3605196594749f5fb69e03dc247a457de09dfef897dee77dd9b146a9838957c6a40b919a921e212fc2becc45a43e2bb2a9e19ff16d8b81e6378c8267f4a64f754d6f00822bc6450ab2282bf7e5e3fa99734be599122e0039d7277b1bd7fb73e62d62e697a614df333aab70e6c8ff28317d49a8a70639f703f02fa2c58c2432fd03d528a1ea7c66c3f8fab3d95f2d663b67665578fe3976c93e978c443748d261383916d4db17ca464f09267e221c038c6ce81e4a56ba73f7a119b95c6cecfd18eac303290fe9de807f7d40fe434a2ce3baaf8614cfb6aac53132fac712be36ff272e103a67e68f779139f8991ac8218b25278dfe16d6aaa6b8b717ecfa8e685d859af7be2233fab8f888c2efa08fecf3a8b4a87b0e5db6ff562f7b872023aa871612d5ffaf47e5e699c3a33aeb73573729c874e7bbf086c8cde4ba2d3293ab3c0af6ec668c5f4a73cdfa13e227428cc45d1b50f51ef1e5a75ff9a6c3da0ed417c1a249a82e823eb34582a18e96cac01e90b7d41a853b49d2420cebf68e878ea4a6a564fbd5f53bc167608f40ceccec109e917a9796a915a92d4da2ba456a964e26c591d4e7b2bb21136aefce3d61557713071ae1eadfe99e71f0d5ef3813f44766c903764dc171ed53976c81d8f9dce0c6019c0fb067c81bf531f3163fcdfd6693c7802ea64cf1256fc9647752b74ed43e12322f35f78a17e82bc88acc51f5eaccf19ebf85d3c44def79c6a12a752965f40e8e77d0c46a24d83e3f26b0c1e625ed77e22fd2e95269e20985de03d03ceba828518f919ad2ed59b45de7be28ab0f353cc63e66a1e126f948515f157193c0ea880d8a5ba021ff33a7db4fbea197d36721951b94df2f231bf293577cd4b6f3dae6e5fbaa4ccd9cfeb23c44b9a4e2642eb67e34ecd5926fbbf526ac45239b6d73c8672f120a1eb2ec25e855a8d849b7b81ba8b1ee18203170412499bea14b55b1c0f0a9e73eb8478c4b9108f38e023bb9467a5a955d81ca6f2a92bac04aea5c5fe8640d208f4910df2fc47fe88185b135674fbdd292e2f12f37695fd20ea77ef6e883f0ffb58eaba750f5f12fc4ba942e52471fe7eace3e928be0df6c659e2bc59d1281007d68e957e615e04fbfd852ccb8873d07a4d33be7fc88fd73ad5395da36b9029c93875537e482a99e2bd8d8ad1467dc2f91e78c7dfa58f98f4a0697dce103fa8bf11ed7d5fb08471c23852afcc33525e807368c61237949490faa5665d7d9f2c72ccafe5e78ee567dfc54b32d4b785c3166d436a34f160027d24d64aba81bf6cb02b699b9792661acf941f823c12cdbb9ee8bcd8c0407dda9c2f0ecc7d581312522f596a624247b9a53c1f6d53cc5acf171ec67160c0e44fdd91ff475ba96ddec73638ade71c501e3f3218fa88439e908ca0ebe40a768de90fd9271ff9797d24e3881fa11ad89a0487556b6744eb13057f9cbaa719951a4e88c3d276b003a631409e035a99d265525eeaa176552fa61e139d55dee9f693e50163de2f347dc4a8df18b827361fd9350f21dc587704fb5542560bd1d27087304ed691ad8f7c9c3723ff23de20a869c5e720bd8037203265c63c20f554ab06188fcf610cb0e46d68cf6c29f55c7d207ba11e9f5767068caed602f926a962eac57c16f3887bea7f4aeda8d45ba7d93caf9f75e64eb171ed31ae89a19f887e75483111a91222e197add4417980aae6ad073d3f337fda38af6a0b8c3f8ee803732366e2dfd6474c39b3eeadf311c9272b501c52f9358c9cd7d5a6abf4bdce2df4087faac7f7e976bc20ff1bf96a5db542526a46827adc39eb59dfc54b4c1f10aab95d87345e6c422269691bd711c7fdda3ce3a3c6f789d513ee498f48a9fba68e69d7d4180955c765dd132d1f9cb275f9887f7fe2456d81291ac71eea144b751d8b8f006d15d2584add0bc870e003a809d2612cce40ffe27ee3b929cc19acd4e7e4a7d115d964ee24deedc48bea8f19631ebfbbfd34be56a07b301f89e66db057b0da87be91a8a52ea41e15afa8ba3f6e6b3c13f5bb2c67691d53a68d8e132d710daa3367562da62edb0fc97cdaa9f4aab78df374826ba9160cfd63d7fa8859eb8bce2d066345ab356268c55b93e72577e36030d4df7fc443626c4411694ce2aa9efd5be8246958ca1dc71d8c189bff9178089e07dc43f1d5e3ffee73ba9cae242ace9cb16332acc321c3ebdd59805a4177d1fcc7789ef6f1ab96ae564ef46f864e11b5c0d2358ecebff7a2befa279c4f3cadd42e49a6d2f5fa23fbd3319f88cf52d74cd28849f0265cc7395c2f6983fffffbfa88f00ec9f130692ff6f00bd333752edd20da03bb098e405383dc5a874f84e3b3505f35a0419e17d45f94baaab0d9a49b54174feb28dfe10fb17988bceb05c55811b2911746d698f2bcbf051fd932e2437855bf48fa08de7f7a67acee472fc0d417fd007a4953f5a17ae985f52c3146252fc8cb48b7587fb17819763fb023b54f43f418758f749b7cfa66ccb6b6ad614e3b1cff3cf002ff7992d745200b3c7bd1f562d7baf9ee35fa73fa88d005a2b909ad2f987e697058e80b0f4a16559cbd964a77577ebf8a382d689fa087abace3b69dd9bc3d705cec984e2add43fd11e786b11605af575b86d5b9fb64bea1deb0fde8cfd2fdca99fe9dc89db63e62d62f8c9353b7d547425bcc62557116e8bb44aa07bc80fd09c44708eff7539fb57d3ea861252b5e7ce16a25be1356632fef8f5ba26db38d0978591a6bf91745914ed5ca1eff727e4d4fd86e9866db9fc7b56aef9c597a605686667f869aa3f410baa347b506091b6c36bd2584229d2bff64f41f1ecea4bad7c899f5d26a3e808d5562dd12e3fbe22cd2132751ed266e03bf888ceb2e6d8f7fbf3e22ffc7ed55db270e8c73252da4a7145f54e61cbb3647f2c186b2945cbc82417f0ad173dae67e66d1235b3f31e995f9bbdfa55f663dbe53a04dafd76c8ad06227f4b307da7c1c9ff80c7fcce035da2f7243f4fdbd49bc2ab8fe91f4044d75801cb120be9b9e6da6d7d0abc6cc8350d141f75bddab31f2a2b93a1c5305de8ddfa7e7ebfa481abcdcc4e735e75cdd37bd54f3fb66ad955de29e7cd67e5e1f31f76a6e7daf1ab23c8e1afbb676e98fdfa735bf754248d21aade092626287d7cbe777c5476a0b67361a63c65827a17b1731e3880b0eb01873461fd4736a59431f09ebb22e029e60f6eb335e22d7482cc183534cafc8feafe3aa6c1ec0f92195d2308a87cfbfa3efe8983cb0f5918f790d284843edcee9eda00dc4d3ca0bf398fb5a1591f5a8b43aae371bf5a61e2fe08e28de6df1443d4e7afcdcc1335974a56a27f84f0fba0470c104673fa5b15b8ac00f4857d46a4fa65390fa827eb1b499567c0a71d04e1803c13a90fa2ed37e4c67cb039d9fffc2f734e6eb7f441f91ff63f76acc9e16f9946356d38a46a6735c8f43ed9a96a255e93c69f011de60e81d01968879df38da6fe72efe290fe17705fdedb0ef23883af7425a2e345fd7f432f985f81dd89614e8335bdabdb092313eb0310d946ed0bbe0e73d132f4e5f514c17f4151def86f71e7ff05ed031c43e77463b10b15e7a5e245f90710a344f820e03a4d4297b169d9097226619a814c1b5a6dc80eb9404d8bcb2d6cc77ea90716bf4e7fd23b2576d395f68356328d2aaa59827e46a8f045fb0b77c84dd0631abc8f0d508ca3a5b95ed311ef3204fe935ea1e65f8e44b4e202f9bbc2ad047a4a6b7cd137ec796928edc47f5bb72561d92669bbef5421b8fe4e8dd73fe083049ccfaea461e39f2da41bf71fcd47f22d7956815d72f17edc5ab3faeff22c92a7d47f158a39bfe207d4fb9efce893f460e8feaf3630caf9fe9f85bf0e249b9071ba3aee7f248be975943d3faa2e29733e730a8e1a27d50b04d35ddde0d50f6a8de8c17581550050395bf2336c034cdf7ead11f6bac46c5bb462bae0d83f9bcf99ff28fc8ff9bf411fbb3994fc858533adfa4a3661d362cb522d20f6a54cbf49d796d402353065ea31daf25b8281217b449eedd96a798f779a65a5288ba087884914fa1d145c12b1e0cfe61c46069f9fd51b26bb7e0212646cc3df9d061f71b5e1325692bcd7bfa8b69b89983835d90fdf8bd10c7a591390e884705310fc29f390e5b68bef6ad287e907e22ec1bc16186e505f92dc1f5c6b8c1ee987eae34d24a42832ea7e78f6380f7c64bfe767d44fcee54175e8f0ac77c2a5aa27d2039c51b8018ad565a1395237f0d8b7d356b3dd53a18f5bc13faed5ff8f39953d4715b05b6d384f5e3173a7f646ef4c36c66fdee6d6898fc2ec7bc042bebd2af94ef0d9b9365bbd2188ac867bf37f2330c5b15be4fbfa45fdf9fb6c0a9628c18b9bfaea800d49dc47b21fd9658f43ace225d7216e301c563693eebe97a5e88bbee46f006e8bdc5b6a5f135617d004f9b239bed6e35734e823973b56f25c57825391aeb9ae2e5a87132698f5ad32453844bca241e61a7aed56756d46f099e5573d207f5515abd7b4d6a54ee5bc6f93bf591381aee7d702fb659a186d3f894ea7547eceacc77342d83b473ec85b67fd173e4735c3fcdbefca95ec2b1ac5a6bb77cec92d787cf917c76c3d398e67ae4a63cbfa905750c4d0dfe95f48fde096143a64f897ea7b976a2b64389bc5f8d197f23d60dba55fa9cee87bc791d2797611c2c5327111f17d70841dd4550b3f69c7810785b5a741973bc247ff3848e13b7d12ab3cd6da7f859dbacd1bf571f31f5019c175fabc77e0fa91fe209eea2da1d6aa57593e94b20ecf460edbc637a96d3b59a52fde9f826592a77c6a3cac9eab29644959bee11be231fb2839c45a9c73e3572e06d5eb22dfe96f0c6291d1b6a770e3b821f16f2108dfec6982083638ed7b27608647fa977b5753c97d8ccdee87af0928c9349a0eae8fcb4e7f43ae501aaa6a58f190739e390fe567012d6fccca86201f35cf59b767f76803c98ca61c6ef1eeb772d46e623c7c7943eaff953bb54eeb513f0fa564e52d7a41765cacbe74cc5e0cdf360ec16f0b367aace385373dc4c9d7deb9eb33d2fffdfd0473eb283dbf9841ec9bd19a59f649a4cdb385e0b3a0baa84c2af92511ae658d1ae4c5bad1aac2497f054025a267a8a6db38fe30d9fbd9ff93b8e17c87404cd22d45e45a2425e47df8ee5b57c1e412ee227fa48246f5cce3f91b6debda7382aacf2b4e4fc9bfa59ed93b14f139e3d2a77eaba2e675ed456283cf9951beb1035b11582dfab39cf74393e4be404d137e477eabe19999b7ddab3a4fdedfac8e6df87b486ce1f38240b6394e74e31d3af9f64de9b8dccc0716b3789ce3cd54d0045e21db6a37a669819553c8da8833a4f09d2f0e799722f51d73274d179e51aed39877089bd20aeecf7311cd35ac7d1fc0cd24242f5e91dd1200ee755948c3c731d0b3b2f691c31ec9e52c5d3194b8f849dd25fcb2bf9e068c6e4ca0ee3d862608f61a70c67feedfcd21fd765fc44075c293e227a9aad8709af3f2bf79a4a8f582432e30c24a09431173927cccfc9b00e9975168389d3cd4c499f68ba9debcc6c389ade06f5c41688a7d0fc8c9ebba8018fec36d1c9a8f14b562a27ce25f5afbc70d6f483ff417dc4a4d59b6c4ca60f5be8cf03db3fd2437f04d48043b22ca2163b383b625d6117923c6d39f6149fe92819b99ef242599ae3bd6269cbefc4099bfe9602d3d053d258237a4589e3a71eb89fe721ed5fc321f90c0f39c647227c085127fa399c47329578683b7eee335f36749b37aa675b35e7d4f62b19f7c92cbc805f577dba87d631f01bd15b3ce3a87ed751fc3ea3f86ef517cfadccf13ef8c8dfad8fcc2d1b939ccf18df9bfe07f1ef66c886d43d5acd32ab4c1208caa8d35e663f36ea7e138d36564d81337c4efd714dada60c66536b8db86779d06a1b7c2467b48fdecbf405934eb2108c46c44d6532e42b89e46d14287f043e045d59075afaa5ed27d9929798fa4809b9e3747ef41e4635229a1d988e3a362b6df091a991cf638ebfd818339abfbab51efc1ed397641258ee819e48d7dc05b1b9aea356b8a3de197a08e2b2152f255fcb1dce6b9f0a70e167b31bf2bf346af089284dbdeab8ab2ba7db01f548ad668b7bba3f6aadec55c6f97bf511931699d7d87926568c4fd00ae43b862e92567467207507cf3897f132dc2592b3870a074d608df4092f57cbca71b5da7fc73f228d311a2163a37af238676051de4bdd46b53bb39060d4b373148fa6f1b31c838f6cc3430c5d26c0c57a0c71abe47d61290f72fd8cb1cdb8dee77c44de0fba5dceb8470c0fd131d6a7a423ea6a6d175ea8f331bfd0fce4997e03dc67b947a543715bd34114f7662fedefd64722b6728b87449bd85066da26a5ed5f780b4763fa81de7572dd945e6dac21131695c44711edd5e86f57540324931f2486a3cc1562bf60f3ca5c6bbf40d4b6b52d8f0cfb4ffe9807c26c498fcabd4c81aa8422661971021deccce3cccde2b596ec22c2c66975118da8eb146e63cbb231474a95001f992cccb5aa8e8279216c9486b37c6ce7b8664926c22b9bc11ca4acf7119c5d3aaf734ca617a3d7f62bf349cf09f33b52ac23e6fbbf2031a1ee14906633bfa66fd507cd4b161a778cf43e5d37b8bbca5c81a22d8789ce3b706fd4f7d5fbc46dbaa87847be3cf027ce4ce36cfda78f98b468132fb1e99c60c29af766bb3c72a4a59a3256499c7fc1bf26ab2c22fc809b8bd599b9f5a275dc4ddeb0edfb99581e19a28b520b16ba4046491c997bc22906b664a2c1fc0bf5bd5ec80f312f6ce717319b44e0a35a28aed331bac25f3c923e6b6cfbb3fb5bbdfb60aee433e79883b66bfa6ed46834e37fc11fea40007f217d2fa39e9d61db95e62fa2c360ee5019f48eb0f0338f466de19431b7df8d3f60bfe7dfab8fd8727f141f58ec3026bf014d2bf23584d7f8007f87a2d59541bf2c1e35f161dfafcbefc3c7102914d6595458c3caad65029f7c54575a7f8f28cf9b1a3a13be3b203f4ea54374103e99d4c8592415bf025658d785ac5e9feb77d1b8244ed19ff79cfae9f20e39e49a0f3e0b36ccc7bc44dbca4ad821ea7d9f08a581f0ac88b7f419eb4bd763c906745f8f63a2ef24ac9882a88d4b6c55922b7212f04bc2e7273d92e2743daa115251ef58ed38eee8977f9451cf6fbd388b96e87cea37a88f9bec977b4039d291fae0313ef7cd633fcba1c1c3e2622136afafffabfa88499feac6e76d7303b6f19d7894bfb06c84f536827a8b563d0c9d69540869b5ae137e46f43ec09c159da210d30fc9db8b7b874dbccfe499122f253c959f01f91cfc0c3c4eef608ee10aea81b03e63f391f76c98ff1fe8288267f516f2aa35ba8ce7d67e73ec6dbe6adbb4d43d331c2f9c415ea4637d7fc1185e45aa8b997931c604dfdb3e2b390a66a37cbf8bb5638f45d5ba4e5f1bf091ef6fe24baff251e2a7dcafde3b79c6fbfeae73bdca8a2d87f329ae65e584f2bba0514b9e869ceb1ef8a0f7820fe2b21f1a3e04a2a5af8caf32774cbfcde7fdb76956d8aa5aaf129ff28d532ccf6a495d01416a95d878bb7136ad7b8a5bc335a8be4d98+ + + + + frmMap + signalTz(const QString &, const QString &) + CityTimeBase + slotNewTz(const QString &, const QString &) + + + cmdCity1 + toggled(bool) + cmdCity2 + setDisabled(bool) + + + cmdCity1 + toggled(bool) + cmdCity3 + setDisabled(bool) + + + cmdCity1 + toggled(bool) + cmdCity4 + setDisabled(bool) + + + cmdCity1 + toggled(bool) + cmdCity7 + setDisabled(bool) + + + cmdCity1 + toggled(bool) + cmdCity8 + setDisabled(bool) + + + cmdCity2 + toggled(bool) + cmdCity1 + setDisabled(bool) + + + cmdCity2 + toggled(bool) + cmdCity3 + setDisabled(bool) + + + cmdCity2 + toggled(bool) + cmdCity4 + setDisabled(bool) + + + cmdCity4 + toggled(bool) + cmdCity7 + setDisabled(bool) + + + cmdCity2 + toggled(bool) + cmdCity8 + setDisabled(bool) + + + cmdCity2 + toggled(bool) + cmdCity7 + setDisabled(bool) + + + cmdCity3 + toggled(bool) + cmdCity1 + setDisabled(bool) + + + cmdCity3 + toggled(bool) + cmdCity2 + setDisabled(bool) + + + cmdCity3 + toggled(bool) + cmdCity4 + setDisabled(bool) + + + cmdCity3 + toggled(bool) + cmdCity7 + setDisabled(bool) + + + cmdCity3 + toggled(bool) + cmdCity8 + setDisabled(bool) + + + cmdCity4 + toggled(bool) + cmdCity1 + setDisabled(bool) + + + cmdCity4 + toggled(bool) + cmdCity2 + setDisabled(bool) + + + cmdCity4 + toggled(bool) + cmdCity3 + setDisabled(bool) + + + cmdCity4 + toggled(bool) + cmdCity8 + setDisabled(bool) + + + cmdCity7 + toggled(bool) + cmdCity1 + setDisabled(bool) + + + cmdCity7 + toggled(bool) + cmdCity2 + setDisabled(bool) + + + cmdCity7 + toggled(bool) + cmdCity3 + setDisabled(bool) + + + cmdCity7 + toggled(bool) + cmdCity4 + setDisabled(bool) + + + cmdCity7 + toggled(bool) + cmdCity8 + setDisabled(bool) + + + cmdCity8 + toggled(bool) + cmdCity1 + setDisabled(bool) + + + cmdCity8 + toggled(bool) + cmdCity2 + setDisabled(bool) + + + cmdCity8 + toggled(bool) + cmdCity3 + setDisabled(bool) + + + cmdCity8 + toggled(bool) + cmdCity4 + setDisabled(bool) + + + cmdCity8 + toggled(bool) + cmdCity7 + setDisabled(bool) + + + cmdCity1 + toggled(bool) + cmdCity5 + setDisabled(bool) + + + cmdCity2 + toggled(bool) + cmdCity5 + setDisabled(bool) + + + cmdCity3 + toggled(bool) + cmdCity5 + setDisabled(bool) + + + cmdCity4 + toggled(bool) + cmdCity5 + setDisabled(bool) + + + cmdCity7 + toggled(bool) + cmdCity5 + setDisabled(bool) + + + cmdCity8 + toggled(bool) + cmdCity5 + setDisabled(bool) + + + cmdCity5 + toggled(bool) + cmdCity1 + setDisabled(bool) + + + cmdCity5 + toggled(bool) + cmdCity2 + setDisabled(bool) + + + cmdCity5 + toggled(bool) + cmdCity3 + setDisabled(bool) + + + cmdCity5 + toggled(bool) + cmdCity4 + setDisabled(bool) + + + cmdCity5 + toggled(bool) + cmdCity7 + setDisabled(bool) + + + cmdCity5 + toggled(bool) + cmdCity8 + setDisabled(bool) + + + cmdCity1 + toggled(bool) + cmdCity6 + setDisabled(bool) + + + cmdCity2 + toggled(bool) + cmdCity6 + setDisabled(bool) + + + cmdCity3 + toggled(bool) + cmdCity6 + setDisabled(bool) + + + cmdCity4 + toggled(bool) + cmdCity6 + setDisabled(bool) + + + cmdCity5 + toggled(bool) + cmdCity6 + setDisabled(bool) + + + cmdCity6 + toggled(bool) + cmdCity1 + setDisabled(bool) + + + cmdCity6 + toggled(bool) + cmdCity2 + setDisabled(bool) + + + cmdCity6 + toggled(bool) + cmdCity3 + setDisabled(bool) + + + cmdCity6 + toggled(bool) + cmdCity4 + setDisabled(bool) + + + cmdCity6 + toggled(bool) + cmdCity5 + setDisabled(bool) + + + cmdCity6 + toggled(bool) + cmdCity7 + setDisabled(bool) + + + cmdCity6 + toggled(bool) + cmdCity8 + setDisabled(bool) + + + cmdCity6 + toggled(bool) + cmdCity9 + setDisabled(bool) + + + cmdCity7 + toggled(bool) + cmdCity6 + setDisabled(bool) + + + cmdCity8 + toggled(bool) + cmdCity6 + setDisabled(bool) + + + cmdCity9 + toggled(bool) + cmdCity1 + setDisabled(bool) + + + cmdCity9 + toggled(bool) + cmdCity3 + setDisabled(bool) + + + cmdCity9 + toggled(bool) + cmdCity4 + setDisabled(bool) + + + cmdCity9 + toggled(bool) + cmdCity5 + setDisabled(bool) + + + cmdCity9 + toggled(bool) + cmdCity6 + setDisabled(bool) + + + cmdCity9 + toggled(bool) + cmdCity7 + setDisabled(bool) + + + cmdCity9 + toggled(bool) + cmdCity8 + setDisabled(bool) + + + cmdCity1 + toggled(bool) + cmdCity9 + setDisabled(bool) + + + cmdCity2 + toggled(bool) + cmdCity9 + setDisabled(bool) + + + cmdCity3 + toggled(bool) + cmdCity9 + setDisabled(bool) + + + cmdCity4 + toggled(bool) + cmdCity9 + setDisabled(bool) + + + cmdCity5 + toggled(bool) + cmdCity9 + setDisabled(bool) + + + cmdCity7 + toggled(bool) + cmdCity9 + setDisabled(bool) + + + cmdCity8 + toggled(bool) + cmdCity9 + setDisabled(bool) + + + cmdCity9 + toggled(bool) + cmdCity2 + setDisabled(bool) + + + cmdCity1 + toggled(bool) + CityTimeBase + beginNewTz() + + + cmdCity2 + toggled(bool) + CityTimeBase + beginNewTz() + + + cmdCity7 + toggled(bool) + CityTimeBase + beginNewTz() + + + cmdCity3 + toggled(bool) + CityTimeBase + beginNewTz() + + + cmdCity4 + toggled(bool) + CityTimeBase + beginNewTz() + + + cmdCity5 + toggled(bool) + CityTimeBase + beginNewTz() + + + cmdCity6 + toggled(bool) + CityTimeBase + beginNewTz() + + + cmdCity8 + toggled(bool) + CityTimeBase + beginNewTz() + + + cmdCity9 + toggled(bool) + CityTimeBase + beginNewTz() + + beginNewTz() + slotNewTz(const QString &, const QString &) + + + cmdCity1 + cmdCity2 + cmdCity3 + cmdCity4 + cmdCity5 + cmdCity6 + cmdCity7 + cmdCity8 + cmdCity9 + frmMap + +
diff --git a/core/settings/citytime/findvalidzones b/core/settings/citytime/findvalidzones new file mode 100755 index 0000000..f9e8b5b --- a/dev/null +++ b/core/settings/citytime/findvalidzones @@ -0,0 +1,38 @@ +#!/usr/bin/perl + +# A Little utility to help tidy up messy zoneinfo directories. + +use File::Find; + +find sub { + if ( -f $_ ) { + my $a; + open T, $_; + read T, $a, 4; + if ( $a eq "TZif" ) { + my $d="$File::Find::dir/$_"; + $d =~ s/^.\///; + $D{$d}=1; + } + close T; + } +}, "."; + +open Z, "zone.tab" || die; + +while () { + next if /^#/; + if ( ($cc, $north, $east, $z, $comment) = + $_ =~ /^(\S\S)\s+([+-]\d+)([+-]\d+)\s+(\S+)\s*(\S*)/ ) + { + $Z{$z}=1; + } +} + +for $d ( sort keys %D ) { + print "rm $d\n" if !$Z{$d}; +} + +for $z ( sort keys %Z ) { + print "zone $z, but no such file\n" if !$D{$z}; +} diff --git a/core/settings/citytime/light.png b/core/settings/citytime/light.png new file mode 100644 index 0000000..2aab906 --- a/dev/null +++ b/core/settings/citytime/light.png Binary files differ diff --git a/core/settings/citytime/mag.png b/core/settings/citytime/mag.png new file mode 100644 index 0000000..9cbd32b --- a/dev/null +++ b/core/settings/citytime/mag.png Binary files differ diff --git a/core/settings/citytime/main.cpp b/core/settings/citytime/main.cpp new file mode 100644 index 0000000..e8664c6 --- a/dev/null +++ b/core/settings/citytime/main.cpp @@ -0,0 +1,30 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "citytime.h" +#include + +int main( int argc, char** argv ) +{ + QPEApplication a( argc, argv ); + CityTime main; + a.showMainWidget( &main ); + return a.exec(); +} diff --git a/core/settings/citytime/qpe-citytime.control b/core/settings/citytime/qpe-citytime.control new file mode 100644 index 0000000..fcec4a6 --- a/dev/null +++ b/core/settings/citytime/qpe-citytime.control @@ -0,0 +1,9 @@ +Files: bin/citytime apps/Applications/citytime.desktop +Priority: optional +Section: qpe/applications +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION), timezones +Description: Time-zone / world clock settings + The time-zone manager for the Qtopia environment. diff --git a/core/settings/citytime/stylusnormalizer.cpp b/core/settings/citytime/stylusnormalizer.cpp new file mode 100644 index 0000000..62de28b --- a/dev/null +++ b/core/settings/citytime/stylusnormalizer.cpp @@ -0,0 +1,98 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include +#include + +#include "stylusnormalizer.h" + +static const int FLUSHTIME = 100; + +_StylusEvent::_StylusEvent( const QPoint& newPt ) + : _pt( newPt ), + _t( QTime::currentTime() ) +{ +} + +_StylusEvent::~_StylusEvent() +{ +} + +StylusNormalizer::StylusNormalizer( QWidget *parent, const char* name ) + : QWidget( parent, name ), + _next( 0 ), + bFirst( true ) +{ + // initialize _ptList + int i; + for (i = 0; i < SAMPLES; i++ ) { + _ptList[i].setPoint( -1, -1 ); + } + _tExpire = new QTimer( this ); + QObject::connect( _tExpire, SIGNAL( timeout() ), + this, SLOT( slotAveragePoint() ) ); +} + +StylusNormalizer::~StylusNormalizer() +{ +} + +void StylusNormalizer::addEvent( const QPoint& pt ) +{ + _ptList[_next].setPoint( pt ); + _ptList[_next++].setTime( QTime::currentTime() ); + if ( _next >= SAMPLES ) { + _next = 0; + } + // make a single mouse click work + if ( bFirst ) { + slotAveragePoint(); + bFirst = false; + } +} + +void StylusNormalizer::slotAveragePoint( void ) +{ + QPoint pt( 0, 0 ); + QTime tCurr = QTime::currentTime(); + int i, + size; + size = 0; + for ( i = 0; i < SAMPLES; i++ ) { + if ( ( (_ptList[i]).time().msecsTo( tCurr ) < FLUSHTIME ) && + ( _ptList[i].point() != QPoint( -1, -1 ) ) ) { + pt += _ptList[i].point(); + size++; + } + } + if ( size > 0 ) + emit signalNewPoint( pt /= size ); +} + +void StylusNormalizer::start( void ) +{ + _tExpire->start( FLUSHTIME ); +} + +void StylusNormalizer::stop( void ) +{ + _tExpire->stop(); + bFirst = true; +} \ No newline at end of file diff --git a/core/settings/citytime/stylusnormalizer.h b/core/settings/citytime/stylusnormalizer.h new file mode 100644 index 0000000..d5e44a3 --- a/dev/null +++ b/core/settings/citytime/stylusnormalizer.h @@ -0,0 +1,70 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef STYLUSNORMALIZER_H +#define STYLUSNORMALIZER_H + +#include +#include + +class QTimer; + +class _StylusEvent +{ +public: + _StylusEvent( const QPoint &pt = QPoint( 0, 0 ) ); + ~_StylusEvent(); + QPoint point( void ) const { return _pt; }; + QTime time( void ) const { return _t; }; + void setPoint( int x, int y) { _pt.setX( x ); _pt.setY( y ); }; + void setPoint( const QPoint &newPt ) { _pt = newPt; }; + void setTime( QTime newTime ) { _t = newTime; }; + +private: + QPoint _pt; + QTime _t; +}; + + +class StylusNormalizer : public QWidget +{ + Q_OBJECT +public: + StylusNormalizer( QWidget *parent = 0, const char* name = 0 ); + ~StylusNormalizer(); + void start(); + void stop(); + void addEvent( const QPoint &pt ); // add a new point in + +signals: + void signalNewPoint( const QPoint &p ); + +private slots: + void slotAveragePoint( void ); // return an averaged point + +private: + static const int SAMPLES = 10; + _StylusEvent _ptList[SAMPLES]; + int _next; + QTimer *_tExpire; + bool bFirst; // the first item added in... +}; + +#endif diff --git a/core/settings/citytime/sun.c b/core/settings/citytime/sun.c new file mode 100644 index 0000000..d3f3731 --- a/dev/null +++ b/core/settings/citytime/sun.c @@ -0,0 +1,323 @@ +/* + * Sun clock. X11 version by John Mackin. + * + * This program was derived from, and is still in part identical with, the + * Suntools Sun clock program whose author's comment appears immediately + * below. Please preserve both notices. + * + * The X11R3/4 version of this program was written by John Mackin, at the + * Basser Department of Computer Science, University of Sydney, Sydney, + * New South Wales, Australia; . This program, like + * the one it was derived from, is in the public domain: `Love is the + * law, love under will.' + */ + +/* + + Sun clock + + Designed and implemented by John Walker in November of 1988. + + Version for the Sun Workstation. + + The algorithm used to calculate the position of the Sun is given in + Chapter 18 of: + + "Astronomical Formulae for Calculators" by Jean Meeus, Third Edition, + Richmond: Willmann-Bell, 1985. This book can be obtained from: + + Willmann-Bell + P.O. Box 35025 + Richmond, VA 23235 + USA + Phone: (804) 320-7016 + + This program was written by: + + John Walker + Autodesk, Inc. + 2320 Marinship Way + Sausalito, CA 94965 + USA + Fax: (415) 389-9418 + Voice: (415) 332-2344 Ext. 2829 + Usenet: {sun,well,uunet}!acad!kelvin + or: kelvin@acad.uu.net + + modified for interactive maps by + + Stephen Martin + Fujitsu Systems Business of Canada + smartin@fujitsu.ca + + This program is in the public domain: "Do what thou wilt shall be the + whole of the law". I'd appreciate receiving any bug fixes and/or + enhancements, which I'll incorporate in future versions of the + program. Please leave the original attribution information intact so + that credit and blame may be properly apportioned. + + Revision history: + + 1.0 12/21/89 Initial version. + 8/24/89 Finally got around to submitting. + + 1.1 8/31/94 Version with interactive map. + 1.2 10/12/94 Fixes for HP and Solaris, new icon bitmap + 1.3 11/01/94 Timezone now shown in icon + 1.4 03/29/98 Fixed city drawing, added icon animation + +*/ + +#include "sun.h" + +#include + +/* PROJILLUM -- Project illuminated area on the map. */ + +void +projillum(wtab, xdots, ydots, dec) +short *wtab; +int xdots, ydots; +double dec; +{ + int i, ftf = 1, ilon, ilat, lilon = 0, lilat = 0, xt; + double m, x, y, z, th, lon, lat, s, c; + + /* Clear unoccupied cells in width table */ + + for (i = 0; i < ydots; i++) + wtab[i] = -1; + + /* Build transformation for declination */ + + s = qSin(-dtr(dec)); + c = qCos(-dtr(dec)); + + /* Increment over a semicircle of illumination */ + + for (th = -(PI / 2); th <= PI / 2 + 0.001; + th += PI / TERMINC) { + + /* Transform the point through the declination rotation. */ + + x = -s * qSin(th); + y = qCos(th); + z = c * qSin(th); + + /* Transform the resulting co-ordinate through the + map projection to obtain screen co-ordinates. */ + + lon = (y == 0 && x == 0) ? 0.0 : rtd(qATan2(y, x)); + lat = rtd(qASin(z)); + + ilat = ydots - (lat + 90) * (ydots / 180.0); + ilon = lon * (xdots / 360.0); + + if (ftf) { + + /* First time. Just save start co-ordinate. */ + + lilon = ilon; + lilat = ilat; + ftf = 0; + } else { + + /* Trace out the line and set the width table. */ + + if (lilat == ilat) { + wtab[(ydots - 1) - ilat] = ilon == 0 ? 1 : ilon; + } else { + m = ((double) (ilon - lilon)) / (ilat - lilat); + for (i = lilat; i != ilat; i += sgn(ilat - lilat)) { + xt = lilon + qFloor((m * (i - lilat)) + 0.5); + wtab[(ydots - 1) - i] = xt == 0 ? 1 : xt; + } + } + lilon = ilon; + lilat = ilat; + } + } + + /* Now tweak the widths to generate full illumination for + the correct pole. */ + + if (dec < 0.0) { + ilat = ydots - 1; + lilat = -1; + } else { + ilat = 0; + lilat = 1; + } + + for (i = ilat; i != ydots / 2; i += lilat) { + if (wtab[i] != -1) { + while (1) { + wtab[i] = xdots / 2; + if (i == ilat) + break; + i -= lilat; + } + break; + } + } +} + +/* + * Sun clock - astronomical routines. + */ + +/* JDATE -- Convert internal GMT date and time to Julian day + and fraction. */ + +long +jdate(t) +struct tm *t; +{ + long c, m, y; + + y = t->tm_year + 1900; + m = t->tm_mon + 1; + if (m > 2) + m = m - 3; + else { + m = m + 9; + y--; + } + c = y / 100L; /* Compute century */ + y -= 100L * c; + return t->tm_mday + (c * 146097L) / 4 + (y * 1461L) / 4 + + (m * 153L + 2) / 5 + 1721119L; +} + +/* JTIME -- Convert internal GMT date and time to astronomical + Julian time (i.e. Julian date plus day fraction, + expressed as a double). */ + +double +jtime(t) +struct tm *t; +{ + return (jdate(t) - 0.5) + + (((long) t->tm_sec) + + 60L * (t->tm_min + 60L * t->tm_hour)) / 86400.0; +} + +/* KEPLER -- Solve the equation of Kepler. */ + +double +kepler(m, ecc) +double m, ecc; +{ + double e, delta; +#define EPSILON 1E-6 + + e = m = dtr(m); + do { + delta = e - ecc * qSin(e) - m; + e -= delta / (1 - ecc * qCos(e)); + } while (qFabs(delta) > EPSILON); + return e; +} + +/* SUNPOS -- Calculate position of the Sun. JD is the Julian date + of the instant for which the position is desired and + APPARENT should be nonzero if the apparent position + (corrected for nutation and aberration) is desired. + The Sun's co-ordinates are returned in RA and DEC, + both specified in degrees (divide RA by 15 to obtain + hours). The radius vector to the Sun in astronomical + units is returned in RV and the Sun's longitude (true + or apparent, as desired) is returned as degrees in + SLONG. */ + + +void +sunpos(jd, apparent, ra, dec, rv, slong) +double jd; +int apparent; +double *ra, *dec, *rv, *slong; +{ + double t, t2, t3, l, m, e, ea, v, theta, omega, + eps; + + /* Time, in Julian centuries of 36525 ephemeris days, + measured from the epoch 1900 January 0.5 ET. */ + + t = (jd - 2415020.0) / 36525.0; + t2 = t * t; + t3 = t2 * t; + + /* Geometric mean longitude of the Sun, referred to the + mean equinox of the date. */ + + l = fixangle(279.69668 + 36000.76892 * t + 0.0003025 * t2); + + /* Sun's mean anomaly. */ + + m = fixangle(358.47583 + 35999.04975*t - 0.000150*t2 - 0.0000033*t3); + + /* Eccentricity of the Earth's orbit. */ + + e = 0.01675104 - 0.0000418 * t - 0.000000126 * t2; + + /* Eccentric anomaly. */ + + ea = kepler(m, e); + + /* True anomaly */ + + v = fixangle(2 * rtd(qATan(qSqrt((1 + e) / (1 - e)) * qTan(ea / 2)))); + + /* Sun's true longitude. */ + + theta = l + v - m; + + /* Obliquity of the ecliptic. */ + + eps = 23.452294 - 0.0130125 * t - 0.00000164 * t2 + 0.000000503 * t3; + + /* Corrections for Sun's apparent longitude, if desired. */ + + if (apparent) { + omega = fixangle(259.18 - 1934.142 * t); + theta = theta - 0.00569 - 0.00479 * qSin(dtr(omega)); + eps += 0.00256 * qCos(dtr(omega)); + } + + /* Return Sun's longitude and radius vector */ + + *slong = theta; + *rv = (1.0000002 * (1 - e * e)) / (1 + e * qCos(dtr(v))); + + /* Determine solar co-ordinates. */ + + *ra = + fixangle(rtd(qATan2(qCos(dtr(eps)) * qSin(dtr(theta)), qCos(dtr(theta))))); + *dec = rtd(qASin(sin(dtr(eps)) * qSin(dtr(theta)))); +} + +/* GMST -- Calculate Greenwich Mean Siderial Time for a given + instant expressed as a Julian date and fraction. */ + +double +gmst(jd) +double jd; +{ + double t, theta0; + + + /* Time, in Julian centuries of 36525 ephemeris days, + measured from the epoch 1900 January 0.5 ET. */ + + t = ((qFloor(jd + 0.5) - 0.5) - 2415020.0) / 36525.0; + + theta0 = 6.6460656 + 2400.051262 * t + 0.00002581 * t * t; + + t = (jd + 0.5) - (qFloor(jd + 0.5)); + + theta0 += (t * 24.0) * 1.002737908; + + theta0 = (theta0 - 24.0 * (qFloor(theta0 / 24.0))); + + return theta0; +} diff --git a/core/settings/citytime/sun.h b/core/settings/citytime/sun.h new file mode 100644 index 0000000..2091621 --- a/dev/null +++ b/core/settings/citytime/sun.h @@ -0,0 +1,57 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +/* + * Sun clock definitions. + */ + +#include +#include +#include +#include + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +#ifndef E +#define E 2.7182818284590452354 +#endif + +#define abs(x) ((x) < 0 ? (-(x)) : x) /* Absolute value */ +#define sgn(x) (((x) < 0) ? -1 : ((x) > 0 ? 1 : 0)) /* Extract sign */ +#define dtr(x) ((x) * (PI / 180.0)) /* Degree->Radian */ +#define rtd(x) ((x) / (PI / 180.0)) /* Radian->Degree */ +#define fixangle(a) ((a) - 360.0 * (qFloor((a) / 360.0))) /* Fix angle */ + +#define TERMINC 100 /* Circle segments for terminator */ + +#define PROJINT (60 * 10) /* Frequency of seasonal recalculation */ + + +#ifdef __cplusplus +extern "C" { +#endif +double jtime(struct tm *t); +double kepler(double m, double ecc); +void sunpos(double jd, int apparent, double *ra, double *dec, double *rv, double *slong); +void projillum(short *wtab, int xdots, int ydots, double dec); +#ifdef __cplusplus +}; +#endif diff --git a/core/settings/citytime/zonemap.cpp b/core/settings/citytime/zonemap.cpp new file mode 100644 index 0000000..337f4d9 --- a/dev/null +++ b/core/settings/citytime/zonemap.cpp @@ -0,0 +1,670 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "sun.h" +#include "zonemap.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// the map file... +static const char strZONEINFO[] = "/usr/share/zoneinfo/zone.tab"; +static const char strMAP[] = "simple_grid_400"; + +// the maximum distance we'll allow the pointer to be away from a city +// and still show the city's time +static const int iTHRESHOLD = 50000; + +// The label offset (how far away from pointer) +static const int iLABELOFFSET = 8; + +// the size of the dot to draw, and where to start it +static const int iCITYSIZE = 3; +const int iCITYOFFSET = 2; + +// the darkening function +static inline void darken( QImage *pImage, int start, int stop, int row ); +static void dayNight( QImage *pImage ); + +ZoneField::ZoneField( const QString& strLine ) +{ + // make a bunch of RegExp's to match the data from the line + QRegExp regCoord( "[-+][0-9]+" ); // the latitude + QRegExp regCountry( "[A-Za-z]+/" ); // the country (not good enough) + QRegExp regCity( "[A-Za-z_-]*" ); // the city + + int iStart, + iStop, + iLen, + tmp; + QString strTmp; + // we should be able to assume that the country code is always the first + // two chars, so just grap them and let it go... + strCountryCode = strLine.left( 2 ); + iStart = regCoord.match( strLine, 0, &iLen ); + if ( iStart >= 0 ) { + strTmp = strLine.mid( iStart, iLen ); + tmp = strTmp.toInt(); + // okay, there are two versions of the format, make a decision based on + // the size... + // Oh BTW, we are storing everything in seconds! + if ( iLen < 7 ) { + _y = tmp / 100; + _y *= 60; + _y += tmp % 100; + _y *= 60; + } else { + _y = tmp / 10000; + _y *= 60; + tmp %= 10000; + _y += tmp / 100; + _y *= 60; + tmp %= 100; + _y += tmp; + } + } + iStart = regCoord.match( strLine, iStart + iLen, &iLen ); + if ( iStart >= 0 ) { + strTmp = strLine.mid( iStart, iLen ); + tmp = strTmp.toInt(); + if ( iLen < 8 ) { + _x = tmp / 100; + _x *= 60; + _x += tmp % 100; + _x *= 60; + } else { + _x = tmp / 10000; + _x *= 60; + tmp %= 10000; + _x += tmp / 100; + _x *= 60; + tmp %= 100; + _x += tmp; + } + } + iStart = regCountry.match( strLine, 0, &iLen ); + // help with the shortcoming in 2.x regexp... + iStop = strLine.findRev( '/' ); + if ( iStart >= 0 ) { + iLen = (iStop - iStart) + 1; + strCountry = strLine.mid( iStart, iLen ); + } + // now match the city... + iStart = regCity.match( strLine, iStart + iLen, &iLen ); + if ( iStart >= 0 ) { + strCity = strLine.mid( iStart, iLen ); + } +} + +void ZoneField::showStructure( void ) const +{ + qDebug( "Country: %s", strCountry.latin1() ); + qDebug( "City: %s", strCity.latin1() ); + qDebug( "x: %d", _x ); + qDebug( "y: %d\n", _y ); +} + +ZoneMap::ZoneMap( QWidget *parent, const char* name ) + : QScrollView( parent, name ), + pLast( 0 ), + pRepaint( 0 ), + ox( 0 ), + oy( 0 ), + drawableW( -1 ), + drawableH( -1 ), + bZoom( FALSE ), + bIllum( TRUE ), + cursor( 0 ) +{ + viewport()->setFocusPolicy( StrongFocus ); + + // set mouse tracking so we can use the mouse move event + zones.setAutoDelete( true ); + // get the map loaded + // just set the current image to point + pixCurr = new QPixmap(); + + QPixmap pixZoom = Resource::loadPixmap( "mag" ); + + cmdZoom = new QToolButton( this, "Zoom command" ); + cmdZoom->setPixmap( pixZoom ); + cmdZoom->setToggleButton( true ); + + cmdZoom->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, + (QSizePolicy::SizeType)0, + cmdZoom->sizePolicy().hasHeightForWidth() ) ); + cmdZoom->setMaximumSize( cmdZoom->sizeHint() ); + // probably don't need this, but just in case... + cmdZoom->move( width() - cmdZoom->width(), height() - cmdZoom->height() ); + + + lblCity = new QLabel( tr( "CITY" ), this, "City Label" ); + lblCity->setMinimumSize( lblCity->sizeHint() ); + lblCity->setFrameStyle( QFrame::Plain | QFrame::Box ); + lblCity->setBackgroundColor( yellow ); + lblCity->hide(); + + // A timer to make sure the label gets hidden + tHide = new QTimer( this, "Label Timer" ); + QObject::connect( tHide, SIGNAL( timeout() ), + lblCity, SLOT( hide() ) ); + QObject::connect( tHide, SIGNAL( timeout() ), + this, SLOT( slotRedraw() ) ); + QTimer *tUpdate = new QTimer( this, "Update Timer" ); + QObject::connect( tUpdate, SIGNAL( timeout() ), + this, SLOT( slotUpdate() ) ); + QObject::connect( qApp, SIGNAL( timeChanged() ), + this, SLOT( slotUpdate() ) ); + QObject::connect( cmdZoom, SIGNAL( toggled( bool ) ), + this, SLOT( slotZoom( bool ) ) ); + QObject::connect( &norm, SIGNAL( signalNewPoint( const QPoint& ) ), + this, SLOT( slotFindCity( const QPoint& ) ) ); + QObject::connect( qApp, SIGNAL( clockChanged( bool ) ), + this, SLOT( changeClock( bool ) ) ); + // update the sun's movement every 5 minutes + tUpdate->start( 5 * 60 * 1000 ); + // May as well read in the timezone information too... + readZones(); +} + +ZoneMap::~ZoneMap() +{ +} + +void ZoneMap::readZones( void ) +{ + QFile fZone( strZONEINFO ); + if ( !fZone.open( IO_ReadOnly ) ) { + QMessageBox::warning (this, + tr( "Unable to Find Timezone Info" ), + tr( "

Unable to find any timezone information in %1" ) + .arg( strZONEINFO )); + exit(-1); + } else { + QTextStream tZone( &fZone ); + while ( !tZone.atEnd() ) { + QString strLine = tZone.readLine(); + // only pass on lines that aren't comments + if ( strLine[0] != '#' ) { + zones.append( new ZoneField( strLine ) ); + } + } + fZone.close(); + } +} + +void ZoneMap::viewportMousePressEvent( QMouseEvent* event ) +{ + // add the mouse event into the normalizer, and get the average, + // pass it along + slotRedraw(); + norm.start(); + norm.addEvent( event->pos() ); +} + +void ZoneMap::viewportMouseMoveEvent( QMouseEvent* event ) +{ + norm.addEvent( event->pos() ); +} + +void ZoneMap::viewportMouseReleaseEvent( QMouseEvent* ) +{ + // get the averaged points in case a timeout hasn't occurred, + // more for "mouse clicks" + norm.stop(); + if ( pLast != NULL ) { + emit signalTz( pLast->country(), pLast->city() ); + pLast = NULL; + } + tHide->start( 2000, true ); +} + +void ZoneMap::keyPressEvent( QKeyEvent *ke ) +{ + switch ( ke->key() ) { + case Key_Left: + case Key_Right: + case Key_Up: + case Key_Down: { + tHide->stop(); + if ( !cursor ) + slotFindCity( QPoint( contentsWidth(), contentsHeight() ) / 2 ); + ZoneField *city = findCityNear( cursor, ke->key() ); + if ( city ) { + cursor = city; + int tmpx, tmpy; + zoneToWin( cursor->x(), cursor->y(), tmpx, tmpy ); + ensureVisible( tmpx, tmpy ); + showCity( cursor ); + tHide->start( 3000, true ); + } + } + break; + + case Key_Space: + case Key_Enter: + case Key_Return: + if ( cursor ) { + emit signalTz( cursor->country(), cursor->city() ); + tHide->start( 0, true ); + } + break; + } +} + +ZoneField *ZoneMap::findCityNear( ZoneField *city, int key ) +{ + ZoneField *pZone; + ZoneField *pClosest = 0; + long ddist = LONG_MAX; + + QListIterator it( zones ); + for (; it.current(); ++it) { + pZone = it.current(); + long dx = (pZone->x() - city->x())/100; + long dy = (pZone->y() - city->y())/100; + switch ( key ) { + case Key_Right: + case Key_Left: + if ( key == Key_Left ) + dx = -dx; + if ( dx > 0 ) { + long dist = QABS(dy)*4 + dx; + if ( dist < ddist ) { + ddist = dist; + pClosest = pZone; + } + } + break; + case Key_Down: + case Key_Up: + if ( key == Key_Down ) + dy = -dy; + if ( dy > 0 ) { + long dist = QABS(dx)*4 + dy; + if ( dist < ddist ) { + ddist = dist; + pClosest = pZone; + } + } + break; + } + } + + return pClosest; +} + +void ZoneMap::slotFindCity( const QPoint &pos ) +{ + lblCity->hide(); + // given coordinates on the screen find the closest city and display the + // label close to it + int tmpx, tmpy, x, y; + long lDistance, + lClosest; + ZoneField *pZone, + *pClosest; + + if ( tHide->isActive() ) { + tHide->stop(); + } + viewportToContents(pos.x(), pos.y(), tmpx, tmpy); + winToZone( tmpx, tmpy, x, y ); + // Find city alogorithim: start out at an (near) infinite distance away and + // then find the closest city, (similar to the Z-buffer technique, I guess) + // the only problem is that this is all done with doubles, but I don't know + // another way to do it at the moment. Another problem is a linked list is + // used obviously something indexed would help + QListIterator it( zones ); + pClosest = 0; + lClosest = LONG_MAX; + for (; it.current(); ++it) { + pZone = it.current(); + // use the manhattenLength, a good enough of an appoximation here + lDistance = QABS( x - pZone->x() ) + QABS( y - pZone->y() ); + // first to zero wins! + if ( lDistance < lClosest ) { + lClosest = lDistance; + pClosest = pZone; + } + } + + // Okay, we found the closest city, but it might still be too far away. + if ( lClosest <= iTHRESHOLD ) { + showCity( pClosest ); + cursor = pClosest; + } +} + +void ZoneMap::showCity( ZoneField *city ) +{ + pLast = city; + // we'll use city and country a couple of times, get them to save some + // time + QString strCity = pLast->city(); + QString strCountry = pLast->country(); + // Display the time at this location by setting the environment timezone + // getting the current time [there] and then swapping back the variable + // so no one notices... + QString strSave; + char *p = getenv( "TZ" ); + if ( p ) { + strSave = p; + } + // set the timezone :) + setenv( "TZ", strCountry + strCity, true ); + lblCity->setText( strCity.replace( QRegExp("_"), " ") + "\n" + + TimeString::shortTime( ampm ) ); + lblCity->setMinimumSize( lblCity->sizeHint() ); + // undue our damage... + unsetenv( "TZ" ); + if ( p ) + setenv( "TZ", strSave, true ); + // Now decide where to move the label, x & y can be reused + int tmpx, tmpy, x, y; + zoneToWin( pLast->x(), pLast->y(), tmpx, tmpy ); + contentsToViewport(tmpx, tmpy, x, y); + if ( lblCity->width() > drawableW - x ) { + // oops... try putting it on the right + x = x - lblCity->width() - iLABELOFFSET; + } else { + // the default... + x += iLABELOFFSET; + } + if ( lblCity->height() > drawableH - y ) { + // move it up... + y = y - lblCity->height() - iLABELOFFSET; + } else if ( y < 0 ) { + // the city is actually off the screen... + // this only happens on the a zoom when you are near the top, + // a quick workaround.. + y = iLABELOFFSET; + } else { + // the default + y += iLABELOFFSET; + } + + // draw in the city and the label + if ( pRepaint ) { + int repx, + repy; + zoneToWin( pRepaint->x(), pRepaint->y(), repx, repy ); + updateContents( repx - iCITYOFFSET, repy - iCITYOFFSET, + iCITYSIZE, iCITYSIZE ); + } + updateContents( tmpx - iCITYOFFSET, tmpy - iCITYOFFSET, iCITYSIZE, + iCITYSIZE ); + pRepaint = pLast; + + lblCity->move( x, y ); + lblCity->show(); +} + +void ZoneMap::resizeEvent( QResizeEvent *e ) +{ + // keep the zoom button down in the corner + QSize _size = e->size(); + cmdZoom->move( _size.width() - cmdZoom->width(), + _size.height() - cmdZoom->height() ); + if ( !bZoom ) { + drawableW = width() - 2 * frameWidth(); + drawableH = height() - 2 * frameWidth(); + makeMap( drawableW, drawableH ); + resizeContents( drawableW, drawableH ); + } +} + +void ZoneMap::showZones( void ) const +{ + // go through the zones in the list and just display the values... + QListIterator itZone( zones ); + for ( itZone.toFirst(); itZone.current(); ++itZone ) { + ZoneField *pZone = itZone.current(); + pZone->showStructure(); + } +} + +void ZoneMap::drawCities( QPainter *p ) +{ + int x, + y, + j; + // draw in the cities + // for testing only as when you put it + // on the small screen it looks awful and not to mention useless + p->setPen( red ); + QListIterator itZone( zones ); + for ( itZone.toFirst(), j = 0; itZone.current(); ++itZone, j++ ) { + ZoneField *pZone = itZone.current(); + zoneToWin( pZone->x(), pZone->y(), x, y ); + if ( x > wImg ) + x = x - wImg; + p->drawRect( x - iCITYOFFSET, y - iCITYOFFSET, iCITYSIZE, iCITYSIZE); + } +} + +static void dayNight(QImage *pImage) +{ + // create a mask the functions from sun.h + double dJulian, + dSunRad, + dSunDecl, + dSunRadius, + dSunLong; + int wImage = pImage->width(), + hImage = pImage->height(), + iStart, + iStop, + iMid, + relw, + i; + short wtab[ wImage ]; + time_t tCurrent; + struct tm *pTm; + + // get the position of the sun bassed on our current time... + tCurrent = time( NULL ); + pTm = gmtime( &tCurrent ); + dJulian = jtime( pTm ); + sunpos( dJulian, 0, &dSunRad, &dSunDecl, &dSunRadius, &dSunLong ); + + // now get the projected illumination + projillum( wtab, wImage, hImage, dSunDecl ); + relw = wImage - int( wImage * 0.0275 ); + + // draw the map, keeping in mind that we may go too far off the map... + iMid = ( relw * ( 24*60 - pTm->tm_hour * 60 - pTm->tm_min ) ) / ( 24*60 ); + + for ( i = 0; i < hImage; i++ ) { + if ( wtab[i] > 0 ) { + iStart = iMid - wtab[i]; + iStop = iMid + wtab[i]; + if ( iStart < 0 ) { + darken( pImage, iStop, wImage + iStart, i ); + } else if ( iStop > wImage ) { + darken( pImage, iStop - wImage, iStart, i ); + } else { + darken( pImage, 0, iStart, i ); + darken( pImage, iStop, wImage, i ); + } + } else { + darken( pImage, 0, wImage, i ); + } + } +} + +static inline void darken( QImage *pImage, int start, int stop, int row ) +{ + int colors, + j; + uchar *p; + + // assume that the image is similar to the one we have... + colors = pImage->numColors() / 2; + + p = pImage->scanLine( row ); + for ( j = start; j <= stop; j++ ) { + if ( p[j] < colors ) + p[j] += colors; + } +} + +void ZoneMap::makeMap( int w, int h ) +{ + QImage imgOrig = Resource::loadImage( strMAP ); + if ( imgOrig.isNull() ) { + QMessageBox::warning( this, + tr( "Couldn't Find Map" ), + tr( "

Couldn't load map: %1, exiting") + .arg( strMAP ) ); + exit(-1); + } + + // set up the color table for darkening... + imgOrig = imgOrig.convertDepth( 8 ); + int numColors = imgOrig.numColors(); + // double the colors + imgOrig.setNumColors( 2 * numColors ); + // darken the new ones... + for ( int i = 0; i < numColors; i++ ) { + QRgb rgb = imgOrig.color( i ); + imgOrig.setColor ( i + numColors, qRgb( 2 * qRed( rgb ) / 3, + 2 * qGreen( rgb ) / 3, 2 * qBlue( rgb ) / 3 ) ); + } + + // else go one with making the map... + if ( bIllum ) { + // do a daylight mask + dayNight(&imgOrig); + } + // redo the width and height + wImg = w; + hImg = h; + ox = ( wImg / 2 ) - int( wImg * 0.0275 ); + oy = hImg / 2; + pixCurr->convertFromImage( imgOrig.smoothScale(w, h), + QPixmap::ThresholdDither ); +} + +void ZoneMap::drawCity( QPainter *p, const ZoneField *pCity ) +{ + int x, + y; + + p->setPen( red ); + zoneToWin( pCity->x(), pCity->y(), x, y ); + p->drawRect( x - iCITYOFFSET, y - iCITYOFFSET, iCITYSIZE, iCITYSIZE ); +} + +void ZoneMap::drawContents( QPainter *p, int cx, int cy, int cw, int ch ) +{ + // if there is a need to resize, then do it... + // get our drawable area + drawableW = width() - 2 * frameWidth(); + drawableH = height() - 2 * frameWidth(); + + int pixmapW = pixCurr->width(), + pixmapH = pixCurr->height(); + if ( !bZoom && ( ( pixmapW != drawableW ) || + ( pixmapH != drawableH) ) ) { + makeMap( drawableW, drawableH ); + } + + // taken from the scrollview example... + int rowheight = pixCurr->height(); + int toprow = cy / rowheight; + int bottomrow = ( cy + ch + rowheight - 1 ) / rowheight; + int colwidth = pixCurr->width(); + int leftcol= cx / colwidth; + int rightcol= ( cx + cw + colwidth - 1 ) / colwidth; + for ( int r = toprow; r <= bottomrow; r++ ) { + int py = r * rowheight; + for ( int c = leftcol; c <= rightcol; c++ ) { + int px = c * colwidth; + p->drawPixmap( px, py, *pixCurr ); + } + } + + // Draw that city! + if ( pLast ) + drawCity( p, pLast ); +} + +void ZoneMap::slotZoom( bool setZoom ) +{ + bZoom = setZoom; + if ( bZoom ) { + makeMap( 2 * wImg , 2 * hImg ); + resizeContents( wImg, hImg ); + } else { + makeMap( drawableW, drawableH ); + resizeContents( drawableW, drawableH ); + } +} + +void ZoneMap::slotIllum( bool setIllum ) +{ + bIllum = !setIllum; + // make the map... + makeMap( pixCurr->width(), pixCurr->height() ); + updateContents( 0, 0, wImg, hImg ); +} + +void ZoneMap::slotUpdate( void ) +{ + // recalculate the light, most people will never see this, + // but it is good to be complete + makeMap ( pixCurr->width(), pixCurr->height() ); + updateContents( contentsX(), contentsY(), drawableW, drawableH ); +} + +void ZoneMap::slotRedraw( void ) +{ + // paint over that pesky city... + int x, + y; + if ( pRepaint ) { + pLast = 0; + zoneToWin(pRepaint->x(), pRepaint->y(), x, y); + updateContents( x - iCITYOFFSET, y - iCITYOFFSET, iCITYSIZE, iCITYSIZE); + pRepaint = 0; + } +} + +void ZoneMap::changeClock( bool whichClock ) +{ + ampm = whichClock; +} diff --git a/core/settings/citytime/zonemap.cw b/core/settings/citytime/zonemap.cw new file mode 100644 index 0000000..8e8625e --- a/dev/null +++ b/core/settings/citytime/zonemap.cw @@ -0,0 +1,21 @@ + + + + ZoneMap +

zonemap.h
+ + 200 + 200 + + 0 + + 1 + 1 + + + 789cc4bd59732acbb2adf97e7fc5b6936fc7cab87492d0433d8010926804089080b27ac88ebe134280b87fbe32638ce19a6beeb99add9d5a662ce6a7c88c708fc6c33d2232f9dffffdb761a7f5b7fffedfffebe3e01fe6e1dfc299bfffdb7f479febf5d7fff3fffedfffe77ffd57319bfd5b3ef9146e8ab77fcbffd7fff5bffe2b5efd2dfc9b974dfecb95525e44e2422ee5c9855ccc65533ebd8bf3b729875b7229ebd2a3a318d7cf3e8d5dfe5f6571dea5c7afe410f7af8bc6eefac9ad18f9357c31cacfdf890b906707ce65915fb83176f9f94731e4095a62c8f3f5252e3afdf7757291fa7d8a71bf7f12e3fe69c6d8c913293fd6cf639b4c7ddfa94f9ef2762e62dcdfa2fe7996ff1e93999fff2246f977ca8ff9d73be04216f537bf729cb40eda777c12177dd7fea1f8caf58fca1759fae87ab6e79331d26b1931dae3b224b3fd3eafc5b8fec8eb13fd5c7e777531d20f7b32f56d04c6eefa774f0c791e28bff47f8ac428ffebded85ddfbe88517fc505b8c0fef14efd0b6cef21f52d509e1af529b2fd9e8664b657be9272dadb6e02571f5532cb3b9fc5688f55518cfe57f900ab3f444b31eaf7ae29c6f5d32399fdd1ff2497907ff799ccf2a38e18e9770fc62effa78cf8caf58fa82dbe29a4bc2517285f6743667d753ec428ef93e517d47e9f625cdf1f8a91df23f52bb0fdb6bcbfc8f15a2f90d91ec7bab1cbefd5d99ba47766216fff815c447fbfb4c9ecafc1b318e9eb0199fdf5b417a3be465931eae775042eb03d8e1199fd79fb48a67efb3e99fa95a762e8b7db8a311e7b336357dedd0bb8c8fa3ffb648ea7cd5c8cfc8e2cbfc8fc87f7c6eefee731f88af662ccf2afae50bf634f8cf4418e7c8bf4b91b0f496f65fdeef364d6e7ec400ec1bb5bf1b5d32f5c830b6cdf55498cfa0eb262d46fdeae477d2c9be2926bef498e2cfbfc2a467ecd8bb1d3ffe5598cfade7e92695f170f62dc7ff4c490c7ff3276f21cb662c817eec9acff9aee677f6aec8cd1ff250fed41bd2c867ccd1e58e321781723bfcbabb1cb2f7b12633ce47c63679fe603b2fa6b20863eed2299f3fbfc057cc5f2f76fe42b8ce7f1907ccbfed42247485fa2fd6ef325b4d7eb52ec872e7f31f51d42bedb02e7abcbb318fd677c11431fbf452ea2fe665b31daa3d7155f3b1eb7c5a89fc998ccf17a1f89519fb58618f9573fc590d75f1abbfc1f4e62c8bb7e11df165d7ed287ed9fff12b37f493fd647e1d118e369042e72fcdec762dcffd03646ff7c27d3bf6bb4c4283f5714e3feac5dcff1bb13439f0af52fd29e6f2b62ce376763cc5f3d31fa6bffc518f3cf5a8cf2ee2c3fe87fdf21d37eeda53fc7d3b96aecd2fb3531f2ab2dc0eabfc7bc31fc939218f9ed8de91fde18bbfc3edfc8579cef5a62da8b1cf916e9eba518e9f7ec1fc9f8807da53cd7b7b0e74d967793a37d873dba2d91974e9f424ef351ee0e2c7b38fe22b3bdf22d31fafbfc22be75e36fb323b3fe274f628caffb1e59e373658cf1d414a33c7f61ecd2bf1ec5287fb314633cec299ffaebcbbd18e575dec5cccf23d3befb6731eba320863cab1732fbdf626fecda7f7d25a6fdd818bbfcfa1f62c8b31818bbf4e1b318f59fdd92d55f2f629457cd89515ed03486bd2a8b51de970f56ff3dec8c317e4a62e4df198b917f3f34c6789e8a39ffb1bca43fbbfbcbaf62e457dc88694f1662dcdf7e23df223dbb16a37e3e1fc811f27fa988391f37c490b799055fe738be57c6eefade0d99e3affa64ecd2eb7932e7a3cdd418f395f2e7f83c3e19bbfb47ecafd71c9fe399b1bbbf5e13e3fe11fbd74d0ee9a79e98f690fade50de25fa5f321f603c0c2fe2921b6fe793d8c77c31100791ab9f2999e3697c3476f767ba62f4c7cca331d2db62e437e1fd45cdaf6763d77e83b118e5f9cfc6c86f224679a33b63971e0562ccf7719dccf925c888517ef7c1d8a537d762d8ab7841e6f89decc4e86f8b9518f9554fc62e7d9b17439fe6bb18f2175ac64efed72b31ecd52514a37df60d32c7efaa20863ce70f31e4d9bd1a43de9298f659f2b3fd96185f361fe52fc6b0876b31c6636b650c7b722d46f95bb6b7c6f7c78d18f9750a62c853a1fec9fc85f58a8198f14f598cf20f4d63979f7f1053ffa5b14b2fb3fe641f4e2531e381ba31e2b7bd18e5bf9d8c919f2f663cb53576e9ef3931e429d8f590675704cbfebc1f8d5df9ef1331ca7fef1ba3bd59dfb24fb5b531fcc90731f22fb3bdae599f77436397df3dc7a3eccd7a21a6bdbf17633c3e4462f49f0ae54bec11e2c71b31eedf5d89517ed41523bfda1799fe7ef149ccf58dbc31e623d66f89f670332353df8cabcf624ef627d304cb5e3c8ec5811b5fc32199fe4bcb1343bfe1abb1bb7f742546fea3aa38bc725c3176e9f72a8ff6e1fc2986fe8b6731ed5bd118eb3d2d31ec43612b86fc930f31caafeb7ada87cd468cfed8ac18bbf4ee488cf2a3508cf21a0531ec6b9007cb1e043963f847cf629417978d31fe2331ed37e54fec03e6e32f31fd938cb1bbbf5210335e507eb4276fc6b09f31f595fda8768c5d7e4f9e18f9b5b3c6f02fba64da83cf8231c6f3b598f2b68c311f283fda83d39331fc61e6277b305b8b51defad618f3d94e8cf2f63d6397fe7625467945df18fad4c8b4cff3be98f167c918f1f1b598eb056d63a46fc5282f627b5f331e69f48c5d798d8a18e50d76c698af2c1de5ad2363ac8f497edaa7ea8d18f9dd53be1bd667361623fd301263becfefc4e82ff7d447f627ba1323bfe154ccf9a16f0cfff54b8cf19d3f8b31be6ab44f37f40feb0f62caa7f26e717dd113633c360332ed75f1d118fea5f4e3fcd6b812737e57fd44187ffb15b844fbfd702346fd36698f4ab4bf8f0531e793580c799f395e4b6cffe1814cffb6037bebcb3f5a6ec8f44f964731f25b3c8961ef6a2fe02bfa8b8b9698eb757563a7dfa426e6fac84c8cf6def68c5d7f187d91d9dfb77d63f43f4f8cf2efb3c6aebcbedd8ff2e67931cafbb4fc505e7b4d66ff6e9dc418af7e594cff2d678cf9f355ccfabf18bbf4fa500c79a662daaf73490c7d1f3bc6981f76628ceffed918f6682ca6fdcd19a3ff5b79d0dfbf13a33dc377b0ec59e7468cf28e6b6357de692b46799f763debdfae67bcc3fa90bd9b94c4286fd33346fb0ec528fffdda18feeebd18e53f7d89d19ef94f32edd97e2c4679ab9331e64bc9c3f9e7e1da18f347284679bb8db1d3efae4066fb859fc6eefefc8b98f7bf1bbbfb3f31bff8b297f1b3b1abafaf8398fee83763fe7c12a3bc6345cc78ef468cf243d687fcb946284679fba198eb612731f4eb7a62e47fe6f8be617cfdd21353fe6b31d7ff2231e47d91fcb497cf6f625cfffc29c6f54ddaa712ebeb6e45e6fcf034216b3e72ed7b95bfca46ce3f1b3f92af30ff4c3ec5180fab5bb2e297ba98f62663ecda6fd613737e991bbbf481e587f13f691bbbf25f2f62c69b2f62f8b7f72199e37d267dd87fee3d31caef67c52caf2c46fe830fb0c6737d2ea63f1c8b915faf600c7bd71523bfcb82ccf1bb50feec1ff74fc6b0af0731eab3f3cd287f2d66f9ef6294b710733c4f8bc6589fef8b693f32c62ebdf12a46f92bc9cbf63b7e193b797a3b31fd7fc9cbf60a57648effcac518e3b322a63f3e32c6fee4b318f21c0ec6aefc4a550cf9ea963fe4c9bf8961ff2e1bf00dedf9dda331da672ce6fa69d618fed3a718f294236327cff3448cfac90fc428ffb545a6fdd8dc88399fdf19c3ded7c590e775658c78632ae6fa54d718f1a49547ff91f5237fae5531c6fef78b18f2bcbd19633e6e8821cf8be507791eefc5ac9fa5b19327d713a37e3e9b64dab353518cf29f7d63d847c9c3fef261d7a3fc07f61ff9877151ccfaa47eb2879db5b1bbbefd24863c837731e43952bf12ebeb59e5d1dfafefc448af703cdd529ea1f34fae7cad5f16cac6ae3e4e186fbef63b1f037211e943d8b3c45f427f1aeec488e7c71531ec793e43a63f1d6fc48c9f4762d8f75cde18f6f54d8cf8fdb162ecd26b4d31e70f8c8fc4bf613c70670c79d762f4c76a568cfca65762e4b76a18c729cf7d32c747b32c467dd6d7c6580ff2c4b00f87a118f2bd3e1b637c7e89215f6360ecd2572331ea672ef9af503f8b83b14b7fb1f220ff94f529fb3b51791c1fd5400c793b4fc6586f517dd2debec6c64ebeeaad18f29f25cf2de4dbb2fd656fcf7b63579fd38b18f5592d1ba37f1ec5902f181a23fd2c867cedb1b1936f9f11a3fe16ecbfb2bf93be98f1455b0c796adfeccadbedc59067766decd2975762c8336b183b79165f62b4effb8d18e321df3376f2166a62d4e794fac97eafbac6384f9017a3be1f8bc6f0bf6fc5d0efc3eea77e6731fb6fce18fed38318fab50231f4c95afe90f7783176fa5ceec9b467ad500cf94fb118f25feac6f08f3ec4dcdf8c8ce1afa83cf6e77ad3d8a537d47eecaf5bbb9ff3b5da8ffedef3540c7d6a4b32e7878bca63ff8e9ac68857aa62c81b6c8c317fcfc45c5fb5eb59df9f62d477e5510c793fd93f35ff349ec5a8dfed9798f349410c799f6f8de1ff0762c8fb7e67ece4f9b0fb216f8efa6bfde36d2846799ff7c6f0bfea6294ffd533c67e41438cf21a2f64add75f89e9bfb48cd13fec7afa9b4d63cce7b4a725b6d733ede92ded418de3f196fa3429ef2de7dbb9f3afaff3852cc67324e67e593e47e67ed5b04fe6fc5bb936c67ac42bb8c8fc864d32e7df684fe67a75b56a0c7fae2fc6f54103acf5a071991c613e58eec08a2fee1fc5b03ff737c6aeffe70662f4ffea511cbbfcf20fe2c9b52b4fd7737eabf5c4a88fe9b5b14bbfbf13a3fc59d7d8951f4dc5283f776becd2979118f3f773ded8c937d88863275fa6638c742b1ff2df0764da8ffb9131fcc95731c6e36665ecf479cc89a1effcc9d8a5676a62e85bb5fca16f752886beed8131fc15b517fdad85c90b7ddf2c7fe8b3527bd2de743c31f45b3d1bbb742f2b867ee7576327ffb42a66bcd93746ff95fef4efbc0f63277fe524a6ff3213439fb7a618ed3565fd68be1e5dc45c6f2b88b9fe7934c6f9bba998fe83e5477d8b62e8eb5d1bc3ffda8ba16ffbddd8a57b563ef4dbc762b457ff534cfdd85e9a8fe32731e5df1a3bf9b6c6943f3276e987ba98f1f0c2d8c9773c8bb9defa620c7fe44d8cf6f237c64efe9631daaba8fae0785bdc1abbfe77c7fea0f97c951743df554f0c7d2f0d63a74fa8f6e0f87b2f19bbf4aeda93e3efd9ee87be33d5a7e6f7b531faaf950ffdcaa198facd8c5dfa4cf5cbf1f6207d38ff871f629eb72d18bbf4f9ab98ed7b3676faac3b62e8bbfd6697feaefae578dc59799c6fd43e1c7f0f8f62fa2fea8f1c6faf596397fe3e16a3fdb607b0fc85cb5c0cfd5a37c6380f711443bf46c318e7453fc4d0efe3d518f6a82b867eef5963a74f6e21467be6fa62e8f769d7737e90fc5adfb81863fd50d7d3ff58bd1a63bff045ccf3f8beb193b75516733fe69b5dfa5b550c7dc61b31c6d785fd53fe4aa323863c77256397fe2179395e1eed7ec6e7d762947fbc13a33fbc7c8a517ef662ecea6f7345667f0ed49e8ad7dac658ef903eeccf7ecfd895ff247dd87f2f0531db8ff2dc72fd7c743086ff7f25e6f996b331d6d32d9dfbd33563eccf64c4f4b7585fb73a5f3711f3fccede18e70b8b62e49fa3fdbde5fa79c513f37986b998ebf10b63f8a32a8fedfbccf6b9657d6f385e7dfa9bf74d63975e647f0af2e0bcf3a7affd02cf1fe4eb62b4ef06f2fa3a1ff6be10a33f0e46c6eefece5c8cf6293f91b9df38ee8bb91fb8045ff13c5a2f4fe67c7d0f797df98ff70531c6e77d8dccf965f22246baf765ecd2dfd662d8dfcc590cff2df32186bff3726b3c71f989393fdc17c55c7ff78de19f3d8b519f998531cecf2cc590d77f3086be5762c85bf58c9dbcf70331fdd19d31f4998ba18f7767ecf499bd91391f9c6ac638af771143bfcc9331f48bc4d4cf37867fa6fae57c31088ca15f570cfdee87c64efed5b598fa79c6d0cfe4837ebec90ffd0eb027b65fd6bd16a33f7a2531f48fdf8db19ee68ba17fab6decd2cf4731fdd3d818f14e530cfd5b9fc6a89f8d18fa2f4363c457961ff5bf3346bc712586fe01fbaffcbfd6d118e7117262faeb1563f8af7931fdf5a1319ef7b0eb511fc1ab31fc5be9cbf969723676fa7a563ec7e79531d26fc4a88fc9bdb1d3b75f15a33e9acfc6f037381ee40f7edd183bfda696cef3753963f817d28ffea0bf3676fa15240fc7fb7a2786bee599b1d3e7a8f6e4f85ecc8d5d7a57f5cbf9f0291043fee3d218fb731d31e4df378da1df8b18f247cfc64efeca560cf93f4263a4ab7f713c1f8fc658efec8ba1cf8767ecd2fd9518ed377b3446fb487f8ee715f591bf57a918c35fbd1243dfa7ac31d6e75ec5d0775b3476fa743fc4dc7fb5fb793e2410439fd5d8d8e9f33115d35fbf3776faecd87ef20f271b63cce77d31cfcf7e33d68f5a62ae9f8e8ce1efa83eb47e1a19bbf4e68b18fa772fc6b05f763ff47fde8bd19e6f0731f47ffb32c67a7153cc788cfd49fee649f547ff72a3fae3f88bdf8c115f4ec4d0c7df1a63bd6925863e8f9eb1d3677c27a63e2763977e772b46ff7d793476fabcaa7d381ebb0563d863da07f35f553f1c9fb1a543bfbb8bb1937fa3fec8f179ae18c39f55ffe1f8fcb2fce83fa97d383ef3ea2f1c6f35d68ffcd5cec9d8c9b7bc1143bef3c418e3e9494cfb5733c6f9db0f31e45b5b79a8cf915d8ffaacefc590ef8ef3abfcdffd42ccf3465d639c3f398a21eff3bd31e21fc9c3feff7230c679a48a18f595b5fb21efa3e4a37f1d5f89215f762a66bc5d35c67e82ca677feede18633ea57dbee57e6f2332c6fea9e461fcd3fa32463ca6fcd99f3a7d31e3db9d18fdfb8bf6d3677cf37225663c7a234679839931d6a375bdcff3596c4f3fe6fe09fdcf20cfe78356c6989fdec53cff4afd826bdc7f6c8a717f3143f6915ea07d0e59de4b4bccf354ae7fde140a3c6f1dafc18a27c64fc6f037b6e422c74b955cc2787a3883751ed1cf80e54f67b662aed7de1b3bffb1f946e678ed1e8d5dfebe27e67eb05d4f7ff8da18fefe49ccf82527a6ffdb37867ffb29867fe33d8821efee60ece49de4c15acfdcecc5a8af7d470c79b63531e41996c590a7d617331e7b3576f254c762c893b7fc204ffb83ccf968198821cf6c24467d457363c407d762c837793446fa8b18f5e54562c6074331e5b3fb21dfb04ed6788fc5b4975331c6e340f9717eda958c31df16c4e80fcb6fc6faa8cae7fc346f183b7d1ed43e9c9fc6563ef4cde5c45c2ff5c5689f8f8998faf5c85a9fff32c6faa8e467ff5e6d8ce11fa97ed9bf7b4363e823f9d8df3b3b63ac5fcfc4d027affa657fafd8f5907fdd1543fe39e5977f383b8ab91eb13176fa7c3d89793eae25e6fec2de18fb495931e47f3a18637ff924a6bf1b19c33ffa14439f4f9307fdb17511a33f76696fe4efc58fc6f0df953fe7b7695f0c7d1e0ac6183f4531d7a7afc41ccf763de48bdec99cef9e0ac6d8ef577d71be9b0cc5dc2f981863bdf54e4c7f6d61ece42babbd381e4e5fc6e83f963fe47d2919e3fc89e50ff91bba5ee7eb1ec47c1e73618cfd8e9198f1d2d118ebe5ea2fecffadb3b193afaff2b5deb833c6f904e9c3fe9d7d31c67e00eb53eb8db97b31f72ffa62c8bb7a1343dec7a1b14b1f5f8bd91f2c1df2be5bfe90b7f821e6fafd4accf5ed8918f53ba81bc3beb37ee5af2d6a62eee75b3ae41f7c89e9bf2c8d719ee9564cfbb936c6fa63560cf99fba62c87f67ccf5b29d31f42b88a1cf59f9b1bfc73d63f82b1d31cfbb4f8cd17f6231cfdf968db17f24fdb47ffb4c66ffdc287ff6cf8f6fc6790dbb9efeed8731ce178ec5c8ff692666fd70be97ff1766c55c6f7f34c6fc66ccf78b648c711ea32c863c5f9c6fb47efc5917c3bf8bee8d71bef241ccf39e7b63f8bb5b31cba7bfe6d33f0c5fc5c87fd43386ff6ad723ff5a854c7ff2fe5dccf74f7c1843be404c79289fd6c3bfc662dc5f8b8de15fefc4287f78678cf579b667e20fe3bcffad31e45b8af93c41608cf66988f93c23fb8bfce78bf263fdb4aac6b0dfecff01eba3bd11f33c6ac518f549f943ca538bc4283f5b15a3bd5e381f862cff79610cfdd9bef2efebf762e6ff6e8cf3a9b48f11ebbfb210b3fd56c6d8bfa07f1851de16fc9f40cf671e2e64ee2fcc72623e3f9a3776f622467b047a9e69d41463bc953b628cb7d950cc78b860ecf2fbba8839ff62fe09142f54f262fa53960e7977a8ef40e709ca1731f79b3d31cfd754c4f0979edec8b4bf5f0d31ca3f18339e2a1abbf4412ca63e2732edddf051ccf3634363777f3d2b46feaba918f22e3d63f857be18f3cda22386bfd46b8ba15f7541a6bdcc758db11e3013f3f9b01b31fb83e4a3bfbafc3476f2b4fb62f6976b63977eda8921df51f5c3786cd43176f2be515ef9a7872731fdb78198fd2b2fe6fa6b60ecca5f5dc4906f5e1073bdfc5dccf5d59d31d6cf7362c8b7bb27eb794a95cffe135e8b21efae25e6f31a7563f81f2b31e47fed1863fdf8538cfa0c6fc43c7f3d31c6f923e9cbf57edfca833ecf3532e7ebd3544c7f6f6e0c7ffa20a6ffd13676f2bf8562aeefbf19c31fb4fcb9be5830c6f987ad98e795d51ef45ff77b63277f4ef5c3fe5e3079d09f9aca9ffec2e224867e6f5d63ac2f8ec4d4cfd2795e58fd91f667d234c67a86ea8be3e1f52c663c7a30c679fdaa98e7e54ac64e9ff64c8cf67b817f1ce879829d31f73b1662e8170f8dd1bef762e8f7b932c6f3f33331edeb9731d68f6fc568bf879a31f4198b19af8e8c11cf9ec4d0275b3476fa76389eb5de59e889b91f1719e3f9b28c98fef2ad319eafec8b391f7d33eced9d98fbed8131e2938e98fa9a7cd0efa966ecf46be4c41c8f961ff43d5f91e94f8f545ff49f0b96cef3a85531cf23d9f5d06f751043bfdec018eda9fea0f5feb531da53fd81e36f581243bffeab18f27faa3ef4bc56cb18cfd77c8a795ebf680cfb3111733faa678c7840fd8fe3ef2536867d947e1c6f4f8f62c8fb7a30c6fac2458cf668523f9fef276a5e89b9df742366fc712de679b1ac31e20bcb8feb4347633c7fd015f3bcc7ded8c9dfea8bb9feee89a1cf82eda378e0f0628cfd154be7f9fb9231f683a40fc7c7a0608cfa0ec55c9f957e1c0f3dda6bc513355dcff8615331863c65319fa7bd18bbf2da6731e469f58c71fe99f3ade28f42648cf85ff2c58c1f1e8cb17f732be6f382cf623ebf583576e5bdb27cc52f8d1b31e38bbe31e2b72731df57f2688cfe5315335e7d37863ffa4156bcf0698cfe561723fffdab31e29f9698fbf3b4ef8a67ee1bc688873a62be8f6426c6fd7bda03c5371fe490fad5ee8df1bcdbbb98ef8bca19633f55d753bffbbd31e2a5a998cf9b4ec45c7f3266feac0fc54be76763777ff54acce7693f8db1df62d723bf06fd03c557e79698ed7130467d6fc49c8ff262eeb7b3be156fd53e8ca1ef59ccfae4f850fc1586c6e8bfae7e4b05bdef21f0c08a5f66af62cc47ad67639c8fbd256bfcbe8879bee2ced85d9f3f92399f94951fe78fe1580c7b34a819e37c7c48a67d7edb8a517e67224679870fb09d2f35c6f587d818fb1d2b31e46f54c590a77b25867ddf505fadff56e7629e4f6e89b9dfb51723ffb7ba31e2ab408cf25a3531e6c3b7bc31d6a7253ff74b961963172f2cd97ef2b7834f31df0ffb24e6f37d2531e47da919239eb574eefff8c638cf771043fe51d9d8a50feec58c7f4ec64e9f99da87f3ffbc6a8cf8c2ca837ef91b32e7fba331f4db14c43c8fa0fa627f99178db1fe5d1143bffec518e72f4662e8d7537b73be5f34c4907ffccd4efef2408cf67a0e8d9d3e5f6c7fad3f9f2662e853be32c6fac7548cf61b6e8c11ff95c5d07763f943df7a45ccfdf76b63ec6ff5c43c8f69e5419fd149cce77f3ac64e9f40f2d21fd8dd1943fe9c98effb8bc48c577bc6d81f2e8ab91f373286ff3513a37d0ab131d2f762b4d7e3c0d8e9f3d21733fe3e88a15f2cf9399e9aba9ee3691e1be3f993b618fa2d6bc6787e6f2ba6fddc1b63fd49edcff1f6fc688cf36a9f62e89b0b8cb1befe2586beaf3b638ca7b318fdf5f4608cf1d81443ff3ec797fce9eacc18cf47a93de84f6faf8d11afbe8b799ead668cfa507fd07a4fdb18e7fdd55e1c7f4f1fc68827d47f381e2fea2f1c8f17bb1ffa4d694fe57fc75531e6db75cd18cfb3f7c55c6f3919237e1a88a1ff62648cf67c10f379efb5b14b0f8f62e897ad1b3bfd1e8dd17e4dda0f9fef17f8ba15439faae4a5bffed236c67eb2f4e7f8dc9c8d713e6a28e6f922c9cbf1f9b61743beec9d98eb27d762c6a3eceff2d78307639c9f1b8be93ff78db1dfa1fc7dcee779639cf75c89f9fe09da2bf9eff5c018fea0e493ff9e37c6fa4543ccf79f548db17fd613f3f9ab2f633c1fcff947fefa7d5dcc78b5668c78a522467997a1b14b2f1cc5b4f71cfff2e7ab5b31cffb948d319f34c5283f9b35c6f87d17f37d6b6c1ff9f3e19398fb892f62be6f47e5b33eabaccf90fa9ee7c6789e6626e6f9b6b531dabb22c678a8b17f87d4ef60ccf5a8d818fb811331df8f427f28647f7bac8939bfd27f927f1ef68c71fee95dcce743a98ffceff642ccf7b7b9fd8a52a0f3451bdc1fc83f1e3c9275fe64648ce72d9ec57c1ff14a8cfa9864c95adf288a917f1018c3ffd6fdb49f6d95cff5bf9c31c66b07f565ebe1cb3b31d7bf6fc4f41f66c6785f8531fdc18631de173a27737e3f0cc4cc6f698cf52e4f8cfc56763ffc8dbad2391f6f32629e2fae89f9bee7b131fc8b4f31caeb34c5286f3c32867fa4f2395f5eec7aca5322b37dc62b31c66f363486bdb888198f497fb6e7d7560c790e960e795ea50fe7bfc6464c7ffa564c7fe6cbd8c9ebb3ffc89f6c8e8cd13e7d31ea2fca1863bd7d2e86bc77964e7fb22b86fcfb6f467d6fc53c8fb316733ddaf2633cf029863ee5b631eadf27eb7d026731f777242fe7b7c137231ecc89393eed7ee83ba988a16ffc618c78a82a86bef3b131c6474d8cf60a4c5ee8f7a0fa60ff8ed83fe46f6627c6983fca62be7fe44b4c7fe3c118f19cea9ffe656e6f8cf5f3500cf9dfe6c6388f782f86fcbd3b63c4a7d29fe3a37d10a3bd06d7c64ebf91cae378e9aabe395e96556327ff7625867e95a3319e7f91fe1c3fdb9cb193bfa7fae6782a4c8cb1ffb511733dd7e4e1f3114331fa676f6decd2d74d31f47db574e85b833f60ebbb8f5331f43d6cc4d0e7b41473fee81ac33fce8b39be26c62e7db71073ff676bece41d5e89a1cf283076e9679397ed773176fae458df7a9e31ae89e94fe78c111f8562ae47583adaf743e5697ec88aa9ffca18fdd5cae77ec2c218cfef34c5d03fdb30463cabfaa4bfda36f9a0fff84d0cfd1f383fcb3f1d3d89217f311673bda9688cf5abb298f6236b8cfd6d4fcce739d87ffc98bf679611733dfc51ccfdc6a398fb350d63945f11f3fc59688cfec6f2e5bf6e2e62fa8747639cff7f1573be6d88f9fe848918fa9d387ee48fb69ac6781f512046790f96cef30da118faf5b7c6aefc665eccf541da8f40fb03928fed776c8b39ff293fd66fdf17e3feb3ea87f5fdd531c6f3b14f62e4978bc4b4c7ec6f5aef6ecdc57c7f6b20e6f83889b95feb8b31fe5ee95fca3f3e3d8bf93c84f267fd0d9662e4f7bc11f379da1d99f5957d12b3fdbf8cf1bc9be465bc753f11b37d551eeb2bbc33c6fe16fb83fce726db27627fb8e37c1fb37e3a6e3cde16e52f2fe762eeef2fc5d0ef6cd743bfd62b59fe7153ccf5e7ac18f662f8cdf03f1a62aecf7a60f9bbbd8a98f1fa8cacf76d348d619fc662dcef378c315fe5c428af51236b3ff545ccf5ea9398e7b32764ce978d92319e57d98b215f253486bf321423ff75460c791e7c31ca7b88c15aaffc5a89b91e9215439ed1d018f67e2c863c9f7363f8934731d74b06c658ef33e6796a9307f24691b16b9f49474cfff864ecf439e97afa831f4363f43fddaff7d72e8d61cf7762fa83d287f351e55dcce7876f8c9d7cf1590cf9a29931d68f3fc9f4ffbeeac6587fbb16f3f99a92b14bdfa8bee80ff626c6882f9a62c8ffe219233d23e6f3d1763ffa7f640cfd661563ac37aafef4fc7bcb18cf47287fae371e8b62be5ff2de18f19cf4637fefbe1a23be7a11b33d1e8de1ff493f8efff597b19377ef8ba9cfb331e6eb8618fa6c3e8d713e8ef561e7779fc5d0a77830863e6b31f4799f1be3f9aaa198fed1d118f173530c7d77df8cf78184623e0fdc3276fa546231c77bd618f391c9cff74fcd8c9dbead2959cf47bc89b9df9635863f178919efbe1a23feb0fb21effbc818fef7bb98fb317363bcdf53fa69ffec9b9dbc15b6afd6232b3d31d71f5bc6381f22fde8ef6d3c6397be1e8bb99eff6a0c7f2827a67db5f2b9be2a7d7daeaf9e8d118fa8be7dc6cb260ff46d5afed0b7fb62ecf49d2a9dfe4db41543ffb6fa0bfd99f6a731f4bf88a16fe1430c7d3f06c64e9fb5e50f7ddfdf8c5dfad3b518fa764ac6d89f517f8ba1df52fac7d0afd33086fdee83b5de5a3988b9de3c33c6f3266531d7977762b46fff680c7f371073fdc3eee77ad242ccf8ecca18e99f62e87b588979fe93fd47fe70bf24867ca78298cf371e8cb11f581733dec81ba37f49de6bc85357f9d78c7fd91e818ff3808357319f8fea8a79de666b8cf8f646ccfda192b193afa1f2385efa6a2f8e97fabb31ce83d37e6abd395b33463cb214f3798d9118e58fde8d713e4af2d03fafb0bee47f3f648ce1af9ec5f4ef3d63bcbfea24e6fb66be19cfbf733cc83f6fbd1be3bcd0a398fb6d0d63c407763dca0fa99ffcf5a6e4657b14cec6580fa37d0819df148df97e9f9298bfc7447b2cfffc4bccfd85c1404cff9dfd39a23c0f185fa1fce543d918eb0f4f628cdf21ec4128ff39b317d33faa1823bd21a6ff60e9183fbd1e99f3c7ebad98fe7dcb18f94dc52c2f30c6fad6418cf2326b63d853ea277f3c3716a3bcc2dc18e53d88595ed518eba10532fd995d478cf11084629477f934c6fc7e14a3fce3abb1cb3ffb2846f979cb9fcfe3327ff9e38da2319eff9b88b95ed83346fcf221a67ff86c8c78aa20e6797d5f8cf2f76d63f84fca8ffef7e39598f6e2cdd895bf1c8a195f05c6787ee241ccf7994b3eb6ffd38bb1936f9317b3bf9d8cd1fe3b32fdeb93ea8ffef5e7cc18f567e990afbc30c6fb764662d6572c867cdebd31fa534e4cf9d6c64ebef53599fe74f54b4cff782be6798b37633cdf501533de8d8d31bf1fc4a8cfd1c018fbef0d31fb7bd118cf877b628eaf8231ceffb0bee52f57c662c667df8cf86621e6f3cf45638c9fb598f1c08331cebb95c5d0675a3746fcb213b33d4263b4475f4c7d4c3ee8d3d1f53a1ffb658cf5d02b31dfe73935c67a5e5b4cffea534c7ff26c0c7deec4d0e7c337c6f33d5d319fe79818bb743f12b37f1d8c9d3e47da57f9c72fba9efef13c23467b1446629e477e31c6fb8aaa62cafb600c79541ff47f5775638c57c947ffd7eb193b7937aa3ffa07e3a531fc13e943ffe0e1c518f62716d3df0d8c315e9ec4dccfce19e3fd458f62bebfe8c118f1a6fa6b0cfdba763df4dbcdc4d4cfe4837e31e593ff7bbc1643dfeabd98cf4f3f18637da321e6feec8bb193bf781643bffac118fe6557cce715d6c6881f4d3eee3f583adf376df9f17d1a2763d833da07ad0f3f491efa47e5b531cefb3d8ae99f558da1afa573ffd5f283bee73b31f4edd48da16f45ccfeda13f3fc5fc7d8c9df7d27d35f9b6e8d619f55dff49fab0363f4cf4f31cff7fbc6783f84da53e3ad610c7b118ab99ef62146fb4cd45fe80f9e6762c873dc18431eb50fc7cb73d718f3a1f4e7786959fe3cbfcbfce56f9727629457b7743effbf14f379afbdb1cbaf45fb2f7ffa5015f37d8a96cef7694cc53c0fbd22b37d7aafc6389ff324a6bdbb21b3be0a2731f72b32c68807d8bfe45f577762969715f3fd87ac2fad8f5796629e47a4bf27ffbb9d1323bd497b16317eda71bed5fa7ac1d58f5fb4f7ede48db11e1790393f7befc62ebd7f05d6fb681ecbc698df7d31d78beec89cbf86b762beefa0640cffe1468cfc875b63bc6ff3410c79f6cf64bdaf53f2d01fef47c6789f654bccf5f63199fe4ea56c8cf396ba9ffaafce609d87290cc57c7ea82ba63fbe3286bf7010d37f7817d37fb0eb595e9bacf3f65b31f7038ac638cf3b10d31fff3046792d31fdb3d018e93331e5d918633f4ae5ebf735243ffddbdec218f654f2b03d5eb2c628af2ea63cb131d2cb62caf365ece469a87cfab7f54f31eaebe9410cf9366b63973eb5fbe9ffdd19bbf21f553ff267ef8d11df4a1e8e97b79d31ce033c81ed7d230331e46d2cc5b06fedae31f6178e629e8fad1a43fe7b31e40dda623e6fa7ebe95f5ecec6382ff229e6f9f88231e2bbb118e51f1f8c117f5dc48cafe662beefbf668ce7338d694f3cb27e6fe856ccf7010d8c11df5f8b21cf3434c67aeb49ccf3e09131d68f1b62aea7aa3e144f7db393ef8ef651cf274e46629e2f53fb319e3a6d8cf1be949d98ed171ac37e4cc5f49f5e8c313fefc58c3f86c6b0b76a5fc5535963f84f64c54beb4731e47ddf8921dfe3a731ce279fc57cff71c618fef9bd98e3e3cd18e3f7454cf946c64ebe90edabf799ec6b62fe3e4a57ccf8efda18f19fca63ff6dc6c6b0877762ae0f748c715eb12de67a68d518f56bf9b3fe0363e8f72aa67e2563a75f41f5457fad2179e8afbdd78d319ea41ffdb5d69331e2d9b998f6aa6d8cf9d3ae67bc5433467a53ccfede31c679348e0fc547a3ad98fe5edf18cfd3aa3fd1dfeb748ce12f1fc45c1fff30c6fa554eccfda97b63c4df7b31edc9b331e2a78218fa4c7d63a74f96f5a5f5fee24accf32bf7c6f00fbfc47cbfc8de18fef449ccf3aa763fcf67f68d616f3c31dfaf66f951fe400cf91f8fc64efe33eb47f14f6d28e6ef53de1a23fe298a793e66668cf6cc88b99ffd608cf315963ff7aff7c6680fbb1efa0cac3ce8737813733d8ff657f14b7d6a8cf396af62ce3f6d31d717d55eecef03d527fb77376fecca7fb5f2e8cfd27e28beb95b1ac37fbe11d39fd989b99eb710d31fac8bd15e05bb9ff11ec75fc8f3e34d63febef49b319eef2c89f97cd146cc78a029e6f319b7c64ede1ae5d5f9a0afac98f19cca677f795c1b637faf2de6fb0aaec45c0fce1be33c8be4e5fb906a2731ec7753f2f2f982e151ccf3d2ef62c6473762ee7f5b3a7fef94f383bdaf742be6fb878ac678beda13f33cedd818cf4394c5dcdf9919bbf2ce3d31e4b9b3fcb97fa5faa43d7bb2fcd11f8ab4ef7a9fd2e5460c799f76c62e7d3a17f3f7cd7bc678bfedbd98f16cdd18cf1755c47cff84678c789cf389e2c7e6c018cf8f9ec58c5ff3c6eefe5e53ccfa9818c35eb2ff446cffc154ccf78744c678fe48f971bde3f322a6ff477b1eb33e5a77c638dfdd11f3f94fdaa398f2b795cefdcbf2ad31f6df0231fb23db2366bcfc7c34c6fbfe7c31ebef608ce79b38de268aafdfc4bc9ef74ff4feae9531ceeb35c5bcde3346f9b48f13ca5f30e6fea7f29ff079ab9c98cfb340ff50ef73babb17f33ce097b1b35ff73e99fea83716c3de2e2d9defcb7916733f0ee3c5f6f75ef362dcbf681be3fcc29798cf23b23cc5b3c19b98e7797d31f29b6cc9fa3d9c9d18f71f0762c6035d63c46f924fe7d5593f8a1f3b67319f17d91be3bcca8398e7350a62c8f7fa668cf5ce8698ef179a18bbf2df597f8af73e32c68827dec5d0a75c36c679e6ba98eb335963c45f961fcfafbf92b5df3612f37cfd8db12bbf2ff9e84f3f2c8c11afeec5906f7e67ecca1f3c8bd99f0ec638bf23f9e94f3ff6c97c5fe4a824e6fbb90ec6989f743fe3c359418cf20f1531e3bf3763b48fea57f160c3d8b5cfe72799fbb52f4b31f707aac638cf2879f47c4f688cf30eaa2ff69f782766fd7c19e379a40f31cf37158df1be6cacefd8fe58211443be6e648ce7f73362b6e7d418ed792de67a52de18fbd76f62c85bf5c5acbfb231d6433664bd7ffe51cce7b7be19fb952531fd918c31d6974662aeeff8c62ebd1288b93fdf37c6fef88398fb61a131d67fa4aff6c376c6389fc9fea4f363eb9e18fa3caec4fc7dc8b331f6a76b62c81fc4c62e3d527bd2ff3d3d1ae3bc9431cfc37d18c31e75c5fc7d9a8131cec3a97ee9ef7cbd8a19efb4c5f4776ec490a7db3386bd57ff617c7627fde81f051d63acff90edfc55dd18f1fd488cfadb4f8d113f66c5dcdfe81ba37e8d21ef9d95c7f5b19e31eaeb45ccf67e36c67933f62fc55b5f6f629edf7832c6f9a39c18f21f8ec688b76a629e2751f98cbf72a131de673016f3bca631df7fb833c6ef2f713eb3fda64731f757a4bf9e67991a43bfae98eb5b9fc658bf5a8b51dff99918f296ed7e3eff7627e6f9f51399fef84bd918ed6fcce7f54ac6587fa888b9dfa4fec0fe5a5f1ac35eb07e159f15dfc5b047b92b31fdc9bab12beffe590c790a5963d8db9218f28c2d3feee7d29ee8bc57f42ae6fedfbb31fcf7ae98bf7f75658cf72b2cc55caf647f533c767732c6f3ea07317f0f6f2de6f3b54fc64ebee2a798cfa7d78c112f4662ae2f778db11e6fe95c9f933c8ce79e1a62beef696d8cf761cdc494f72c86bca79531f6bf2d3fc8d31c1ae3f904b53fedd13de7577bffd2de18f1ed45ccdf5f3f8879be7b648cf1d514f3f7bb1662be0fa4668cfeb21473ffdde4e1fbc22d9dfb3d9c3ff5fea7fb85317eeff043ccf71d0cc4fcfdf42b633c3f5f12f37c4ad918e74b252ffbdfe7c118f1f944cce74bde8ce13f4fc5a8ef06e7b788eb07c38a18f23c7b62c8f3b132863f7027e679d8ba31c64b5b4c7f4cf5a5fe726b8cf77b583a9f0fab19637da42fe6fa2dfb83e2d37ad118e7333b629e876d1ae3fce852ccfeb011d39f65f931dbe7a52be6fe78db18e7874e62fe3e796c8cf50cce1f8a77c317639cdfe578517cbbdf1ae37ce75eccfef126667958bf0827dcdf9ecc8cd1ffca62e4bfec1ba3bd1fc47cbe85f5a97879ba34c6fad8a718f9cda6c6887f55bed603743fd703661363bcff7321667e33633c9f26fdd81f1bdf8cfe217926983f1e4b62fede6cdd18cf4b15c43c9f3e32c679887731cabb3b1abbf216ceff0d6cff785e22eb79d66731c6dbe4c118fbb74532e39f45d3d8dddfd88ab93f7345e67ac0e39d18e9830358f1e87320e6f33f6732fdf3c6d118cf83e87efae7ed480cf97bcfc6aebce71b32e3bb8f7b319f27f0c53c6fd412f3bc94aee77ede712ee67ee39db193ef521673ff682fe67e45df18feaf31dfcf60e5a13e56ef62fa974fc6d82f62fd295e0b0fc64e9edc8718e5ef56c6f02fbec4287f773146bcd012a3fc304766fc55d4f58cb7b237c688072c1dedf7f92ae6fb02fac638ff7525e6fb7aad3cbedf616e8cfd27e94bff32927e8c8f1e2ac678fefd59ccf8f4648cfd979198eb213b633cff64e990675e36c67a96da83f1d04ee5d39fdca97e180fd547c6e8ffd29ffb57fd8d31ce2faa3d190f45944ff1d0bc23e6fb270662c6bb2763ec7f67c53c9ff6628c78f7594c7b5113f3bc6a9bccf97bf726e6f3b313639c6fb474beef626a8cf3cc2b31f4cf1d8d5dfa93a5f3bc26fbafe28dc6a398f1d1ca18e7c90a629ef7d91ba3fc8c18f997d9ff144f043563f8174f62f6ff8231d6dfb662c6173d63ecdf8ec57c9fc09731e247f617c51bef6731d7efaf8d317f8fc57c7ef3cd18fee15cccfdc84f63f85fcf62ae5f35c87cbe23ea89591f5563577e47f2d0bf9b9d8c51fe8798ef635889196f537f7bbfead118fe5f47ccf7b5a83ee8df95df8c71de6222e67a56cb18f1e7528cfac8978d717ea42d46ffa8df8ab9fe3d2333dea8168df1fb2496cef743c462fa677d6327efbe22e6f3472b63d4ef9518f215d91f157fb47662c8f3762de6fb12f662ee67d9fd7c1fc4a398bfbffa648cfabc88f9fca295c7e7171662c85763fd47dc6f6ccc8c9dbc075fccfde858ccfddd7b31cfcb558d317eea628c9f3ac78be281a7ad31ce63aa3e743eb6690cfd1a62949f2f18bbf29a5d31df17630cfb74e27c14b1fdb65363f8f39297f662f46a8cf527fa138a0fea2731cf2f178c112f1fc58cf7bbc658efb0ebb99ec8feaff860d03746fc168ab9be736d8cfdee8998eb6b9c5f141ff46ec57c1ead618cfd5be9c7fa5f79c6b0a7763f9f57667f52bc31681bbbf2de252fc7d37e670c7d1ec47cfebb620c7f5cf5c1f6289e8c61bfd95f15af5cde8cb17eb01373ffbc688cfdcb58ccf8feded8953fff10f3f7a1ec7aee97de89d95fd8de8a77eec6c6aebcc9540c79264b63ac1fd9f56c9f8531e261e9c7f62fb2be140f9d5e8d515e24e6fe6dc618ef97b474eedf7e1863bc97c48c6f69df141f9dbb6296e789a9dfdc18e9d287f1d057de18fd2f2be6fb0f607f22c5471f3159fb7b282f52bc12de1ae37d296531e39b17b2ce2b2fc4dc7fbc33c679bd8618f66bfd618cf843e9fa7dbdaa98ebbd6d63975fef51cc78e6c618cf2b4a7ec62bcdbd98ef435a8af97eb59698fb6b5563eccf305df1c66a21e6f39bbe31ce5fbf93191fbcccc5f4373362fe9e9031cf6b558cf1be3aea277f7eb53686bef762becfb065ecd273763ff2af7c33f2bf2273be7d93fcf4dfbf3662e41f1f8ce1afbe8af93c20fc9b48fe786b2ce6fb25eac6d84f9a8bb93fdc30c67af9a798f1efd918ebe50159fb09c6287ff920e6f34696cedf136c8bb97f7025e6f9e5a231ca63fdcb1f7f9c18e37cb52f667c101a633ebf17f37dc537c6e80fd257e7b9dac6385fb011f3f9a01e99f67e5d12733eac19bbf2e7aa3fb677a52be6f89889517e8dfac8df3e8d8dddfdd5a998fb6173633c8f722f663cdc31c6fa4028867ef52732fda9f845cce7533c31df37da3586bffb21a6ffb81633fecb1ba3fdafc96ccfcf8a31cefbbe89b95fdd32c6feff4accf1d733c6f9d2bd98e7e10664cedf5155ccf7e7778d5d7a55f733be6a8e8d11cfd09ec97fcd4fc4dcffef88f9bc27f3d37af54359ccf8e52ce6f3cd1b63f46f5dcff9ac3d3786bff628c6fd27b69ffcc3d348ccfda0ae31ece58398e74b589ff20f3f3362947f9c8ae9df2c8d719ef94dccf799b2fde40f6e4f62ee57c6c6f05fb662ae3f7d1923dea7fef2ff668198f1c58331c6a7f2577f2b1be37c8ef4d5fa0eedabfcc17324a67f3334467f5279ec4f97bc31cec7593ad7d75f8c5df965cb0fe5dfd1de9bffd734c6fbc20331fdbf8c319e2fec89e98f8c8d5dbaff26e6f3d7efc6f04f5fc5ac0f8e6ff97f9f7b63f8631d31e4890ac6d81f388bf97b6a1563d48f27e6fb42d9bfe40f36543efdc1f7b231ca9f88597ed618ed3312339edf1823feb0f2f87c7f6c8cf1a7fa97bfa8faa7bf18df18c31f36667f691ba3ffdf8af97eb26f863cce1f0fafb41e3ee982e50f4e5b64ad577a64f9631331e6ab59db18ebbbd764ae0f6f7762aed73f1be379f808acf5dde9ad98eb89d762dcefcf8ce19f95c9f4cf025dcff5f8bd27a6bc356377ffec854c7bbedc92b5be3916237d9c07cbbf59ad8c519f3d31fdbf0763f8e71b32edeff4438cfc8a8131ceb38dc4cccfd2b95f3020ebbc8c31f22b7862fa174763ec97ccc9d4f7732de6fb014bc688379ec4c8ef60d7d39f627bca9fb874c45cbfdc89f9bed9404cf9e6c6584f64feb61e772566fdc562fa5f77c6a88f5b31d7c733c6f0bf5ec428bf6de928ff2347a6fdae158c71de6229e6f3353b638c175fcce72336c6380f67f9f3fd4f2fc6184fec3f21edf9742ae67acead31f62b543efdbf97a618e5bd57c53c1ff9618cf7e1b2fe6dfdad2da67f766b8ce7174e62c8139e8d71feae2266bc64e9b40fec4fdaafdf2ec43c3fd413733fec620c7fe041ccf3a22363f4afa198f5f94ed6fa4f5dccf3582d31df477f31863cc63caf903376e921fb83f6e3479fc6585f698851de8bcae7fc1d3f1863fddf18e56df7c6d82fb3fce8ef6f8cb1ff427b2dff2a9e89f97c4cc618f3f38798efe3898de1cfe5c42c8ff2c45cdf19adc49c7f7d31e3ab9e31faeb9d18e59dcbc6f0c7242fdb77712d46ffa94b7ecec775c9c7f9789137c67af5a798ef33b574fa972a8fed7bf7640cffdbeee7fb61d89fe5af0ddec4f43f1f8d719ee95d4c7f6d6fecf25f5c89b9df3131c6783b8a79de93f393fcb5eab3b12beff82e667d148db1df5e1533def68c118f3c8ab99e7d34463cb615f3793df63ff967d140cce71b9bc6583ffd12f379c1b631dadfd2197f978d31bf707e92bf766a89e91f3d1b637d3512f3f7204263f8939f62faf35fc6188f5762c8f3c5f691ffd63b8831fed796cef53e633effe41963bcccc4902f6c19c35eacc5dcaf42fbda7a5ed027d3bff16a64fa675e864cff6bfb0ab6f7ffecc5f47742b2de4f7914f3fcc3454cff2c3676f73f9ec89ccfe24f32e71b1ffdcbd67ffc2732edb57f4be67ce9b5c5d46740667e01fab7ad4f1c1e8df17c455f0c7d2bb7629e57b074eabf20733e297f8979fe60600c7fa32ba6bfd63186fe7332fb4f7f628cfda7bc18e51ddfc4fcbd2b4ba7ffd412f3bcfcd418bf277126d35e545f8dddfdcb2731f22f578de1efa93ef47eca95b1cb7fc2fad67ac5e4464c7f252be6efb7dc1a637c37c4fcfdab9131ced356c55c8fb1fbb95e6be5f17c6840a63db97c89517e5c10d3bfbd37c6f9e39918f9b5258fec4b460c7d87925fefc36f1b637fec45ccf743dd19c39f55fd713ee95d8cb15e2ffdd9fecd0f32fd8b8eea97f349503186ffb516a3fce89bf17ccf52ccf561f677edc7553a629e87ae88d97f1bc6981ff762b667cf18f5abfc68fff35331d70356c6f0afdfc5f4afe7629edfe2f8d0f9bfc70f31cfef066294b7b574d457f9c518f349468cf2cb6731d79b7364d6f7d3ded85d5f577db0be8f4363979ebd16f33c17eda9d663b22d63f8df4b31e48f3b623ebf7436c6faed5accf7a7dd1b637db829e6ef276dc41ccfba9ff3f7312be6fe5e49ccf1f5628cfe9411737df5640cffb22ae6f9094f8cf2df9ec99c9f1b0763ec0fefc58c478ac6f0876331ca7fce19a33d391f6a3ebe3c88f97ccbd418fe822fe6fb91abc6580f1b88e9df5a7e7c3fc344ccf8c8cae7efffb9fe1dd97a8b772473becee4c99caf333db0e6e7bb3659ef671818e3f99d1d99f6da5b8135df7a5b32ebdf9b9035bfcec8bcbfc574cd9fabb298f3e7c218f777c9cc7ff548a63d9b3f1bc39fa88a198f0ec91c2f6f336377fd6229e6fb40585f9a7ff29e98ef036f89b9ff3536c67e8d5dcff5888631d66fea64f903ba9ff3c9fbab98e791aec8b41fb53763d8c38118f7b732c6785e4ff9b33e163932ed4bf5ce18f6652546fec59d98f5eb83755e635710737fef45ccf9f720e6f3796bb27e8fa323e6f9d86b63d81763aed7b17d656ff357623edf343446bae465fd856563c8c3fea4f8aa2c79699f9b0f62dae38931e2f9ae98fb49763f9f37657dcbbed6bfc4c86f3833c6fcb716733d624fa6fd9c5c89f93ebb82b1bb7f9c11d37e1d8c614f1ec4fc3de77b32ed616b24e679b08598bf5fccfe217bb6df1863becc8bf9fec0b631e2f558ccf7f13b7f3e8a65af565764da2b8fe9b25719a6cb3e751ec8b24f68cfd8ecd3862cfb3425cb3ecdc9baff0296fdc9dc92797fd0252b1e3992653f307e638df75395ccfa9e9ec418af1f25639c071e8aa95f9eccf1dd6f1ae37a9547ff7d7163ecee2f4664fadf998c31deffc2fb63dab327eaabf595565dccdf23ef89b91e1b1b63ff7f23a63d1a1a63bcd5c8f4b7f20b31f72f2b629ea77f37867d5d8af97c3cf5d3f88ceac6f08fdb629e97c81963bd7a24e67aa2670cfb4a7d345ecfb131f6e7b6628effb631ce9364c58cbfd8df343edb5b63ac8f1dc5d4df37c67e38fb9ff9274331e56f90b99e305b8af93c45cb18ef4f943c1ccfc767633cdff821e67a815dcff3cf1931eb676d0c7fd8d99fc45b977f5207dbf86b9235fe96608dbfa047d6f87d256bfc6dc9da3f607e1a7fe388cceb276f648e87fe08acf9eaad2346faddde18efeba17ceadfa38998ef8bc81b63be7a24b33f7f168d5d79e79d98e7bf5bc688df9a62fefedcd618fb4d2f64f6e74e598cfcbe96c6286f2ae6f9eb2763ece73c80355f7d2cc45c4ff81073fd62628cfc3764f6efe024e6fc7b6f8cf31ec6fc3dc1c818fe11f5977ffe1e88393e1e8de1ef5c8b999ff4e1f346b3d818eb69a198e7eb32c678feeb56ccf3a137c6988f7d31c64774658cf5fcb998ef5b888cf1bcc89d98f6e3688cf731b4c56c4f670f639b9f5a7932fbc3e089ccf66ca2fd62edbf74bec41c2f5d32ebfbab29e6fa458f2c7ffa8dacfcd1bf628d97f79931e28b90cc78f06e23e6f3032531cacf1ec53cdfd53246f9d44febf3f58531def7341223ff69418cfa7c7f16f3f90e95cff175f18c713ea74fe6f98acfc818cf3b96c53ccfba30c67986ac98f1beea8be3b12279381e5f60df62c5f3d58d31ce1b7c8921cf2e67ecca3b64c45c2f6f19e379da3b31e3cdad18f5f35515f37d151531e4fb9a92e9bf7f5d89f9fea59931f62b42317f3ff7cdd8a5af7c317fbf2912f3793031fd85d3c518e7194a6294bf0a8c51be319f777e3576e9ddae98e537c47cff49510cfd9fd83f654f2e2b639ccf96bc3a7f513276e9d3b518f24eed7ecaabfaa0bd296f8d5dfa742186bc93d818f6c698fe50cd18e94d31ed71ddd8d5b7affaa1bd0933c658cf7d16f33ce4d8d88d9777a7dfe45afe682f24d35e545760d98bc5c418fef21d99fda3d21673bdad27a6bd1889b97e5d36c6f34c0f64b67756f971fcfb0531fb77c918fe774ce6782fe7c5eccf4fc638cf5611733fea24e67c762fe6ef51dd19e33c4b00d6787ed889f9fc406c8cfa298af97edcaa98fa0dc47c5ea46eecca3b8ec97a1e222be67cd735863d1b89a95f474cfd4e62ee1f5c93f5bcf054ccf3504563ac4f86623edfd13276e9cf2f623e8f7127e6fb936ec48c974ec6f0a79ec47cdefecdd8c9db503ac7efa1648ce7ab0f62ca7f6d8cfdcabc98bf97f06e0c7f5aedc7f1bb0a8df13ce7ad98eb7d53638c5fb507c76f3434467b1b73fc3e1ae37968f5278e5fbf6f0c7f12fd77a2f9fef102d6facdf42ca6bf3823eb7c4487ccfa6d6e8c5dfaa146e6f8a88fc5b83ebb3046f9bc5ffdbf933376f5392e8891dfdb9398e7d1afc4b40f5963acc7b13cf5f7eca731f6178a62fa4f8198f6a727e6f3b19e31cebff5c9ecbfd5584cfd4331df072479587fed9331fa679dace73d42633ccf7623e67af39d31e68f9998e7192bc638dffc2ae67e53c1d8a5c7be98fd2f67ece48f1ec55c1f9d1aa37fdaf5fc3dcf8d31fcad43c64b3efe7fea3b1364bc4c988932b1fb4c32d3e43b48fe3ecbcc93f4c50fd7cfedfac0ee5ff2efcbcc2a33cfac93efeffbc09bcc36f9a4d7ed7e2877915e97794fbef749793377ff47e690fc3bcc7c668e995372cf39f9f78f72b8efcc57e6922927df95448e7d921e6676eebab2932b95fdce7d5793cf7da696a6bbfbd6943ffdfb83bb4e72ec7efaf692bcd3fc1e93fa307d7ffa4ef378729fbafb8e584eaa2fe40c71dd9fd63fca4df5803c8d44bf59f29d96739f69fe54dfdfe507bfd1e3f7f34fe56ba1be5dfe3fddf7a3fe890c903bcc3cbb4fcbe9e565daeeba4ef2b1f6d07d6939bfa89f9ffbc93fdf3f67497da4ed1167baae3dc2dfb6573a46322f995ea69f7cfe73df03f7794dfefd9619269f41f241fa88e93f5fdf77f7f43263fe3dfdcedaf5df9ff4efb94cdefdbdf09bfb919e25233d9f293a19ae32d7c96794f08f798df8b9617ea5cc6de6d5cba4699e97c9279f9e93eb353348fe0d7d24e78bc93fb0cfcb4f69df9f41224772bfe77b01af533e3fea9fd49317e2fb3732feaa1efeac1d7efc649deeae1c2ff0a25fd4bff442f97f9cffc0da7364727ddf37fe45f93f7f523d63777dfe77aef9aecf5f7fff6bfd73a4f6b4f6f84df9e918f12699d17ffc3375df85e473493e59fe3dfbc3bfffcae7d7d7ce32256f6eff2e249f71f219b90ffe36b6eb16c927e1c43e8cddb59049f26593efacb74cfebd4affedadbd0dcb9cb38c6df2b7f483b293bf79bb9fe4824edbbfa497ff3b3afef6b3fde1f3abf47fb42db64e1fd58ff7bbe5fef5bc7fef3efd7bfc27d7173233eb1fffb83effbecfafda63e4e6118dffffd427fbc3bf0bdefbbf31ef016d40decd2505fe6dec3eb061237e8f5dd97bf7197b7bef23b9eff0635edea793338bef64147cba79067fcf7b6bf749afbd72e93befe89dbc4fefec1d7fa39ff4d5e7d7f571e5f27949e678cd71bf773f3ef95ffced8fcbf8a34fe1877fa732fc71d97fa57df3bfb9f6e77bd51ebfa767faefe57fb0fffdb9fc7fd81e9c477ecf86fc7b3eb281a98dde7a5f7f600fff395b76e1f7dcd9a1647ef00e9c4bc666c3666efec07c90daad06d3679c473487387993113077328fdcf7c46c5cc1e690b99b67ca6efed9fc9d8dffb697bfd2756bf6fc83fffe57f4ffe7dae3db662ffee53cbfe7b8d16ff8fb6fe33ff914bc4af271f5efeaf73fdb1fffc1f6f81f9b47642f0adedd3f6dff7ee7e355131b5f457ce162869fe690242df579dd77d2024767f752bbf5ca98e2eff34ce311e7977af7a96f9dcc3ba1f357178c45d21828b1375ecdcd2d3fdb5dc55f3fdbd8efcf15e7ac3bb3e97f5c1fcaeffbfb9fa9ff9fe726378f780f3fc8fb8fe5fbabf6fdb93cc55063fb0cfeeef3db79e4efebebcfcafe77cc23d9440eb5c74fe5ff8fcc23b22fce267b77bfb4b7bfb663bfb26b8a21befff6e83d7975af91c41023171f4c3927e033f29aa9bd4f3ef83ea7763fb372f2689e28fcf049e7a1563237a5dfcf5edbeb785def25f9f4bc7e323f25adea0d92bfcf92bf2f92eb5fcd16fe6c3bffd8c787bd5afe8efebfbaff9fb7f53fcf65bf9573fe2fe58d0fea606671c7b7ccb3bfcbef57f308da436df6f7f1d7bf6f0efdbd79e4efdbc3ca77f388c6ce7fea3bb54f3fce233f8fd51fe386d10ff789658b0b991fe708b776e2a56b22c3cc9537f2c65ed6cb7979afe015bd2befdabb493e575e29f9dcfa4930e6fb7e90b9f2c3e4da61727fc47b938f1ff9b17d265edf9ffa337fee2ffca5bff2d7fec6dffa3bffdddffb1ffec1fff48ffec93ffb5ffe25f97fd9aff8777e35b967429f3b9533cdf39e6b3be31ff4f9f1e3fee6d77ea9ffcff5f0af7effc13c92ccad7393fb9fcd5ff3c38f6b913faebdfd52f71fdab290c9fb0fae8df5f9e3fef1efaea79fdbe3d7f3c87f7ecd20f5fbb136b474e333fdb7fbf676fe631a53d00f756b476e0c17143b308f92ff94c614a9fdf6eb7ec32bfa4dbfe53ffb6dbfe377fd17bfe7f7fd81ffeabff9437f947cc6c9bfb37ececffb05f7db95d7fe8d5ff26f834ce0057e10f8eb2074ef2c9a04d36016cc8345b00c56c13ad804db6017bc07fbe02338049fc1313805677f187c0597a01c5482bba01adc07b5e021f93c064f413d6804cda0153c076d674b4bde25e804dde025e826b2b69d0ebfb65ff3c486cf7e595f05d549d063fc93c6482e3e4ad9fd4d6b79a5bf50ffbf2d776aeb7259d71edf735bc1c9af3ce77fa15d110f16d28f6b1fb41bf249dbf162f15b89b15cfa777c2ed6b6a3241ef9a379a1606b718a2dd3fb276e4db1f09764fc2bf5f3dd1ebf99bfdd3cf29f9c43e06fc3bfcfa6fe7b32564b892d5fa7b141fa1df4bd9d5b931a0403ac1d25df57ba2ff1fd6f93cf551a0704afc15b300c46c138c806b9201f14826270155c07374129b80d33a117fa611086e9d392e1249c86b3701e2ec265b80ad7e126dc86bbf03ddc871f091fc2cff0189ec273f8e5e7c24b580e2be15d580defc35a92cf43f8183e85f5b01136c35692cf73925f3bf9ee84ddf025ec85fd7010be866fe130e151380eb3612ecc8785b0e8de93711396c2db281379911f055112cbfc6e4c304a6cb87ce21f6c63a27ffaefdb28ca60ffa1e4d5828e57cbf4bd4b14676e13db9cd449c2b9243d49fb4bb6f4b7e57ecfcb2f9421fd7729adf7a43dd6d66ebffdfebdfc0b5ec6e6f8beb78826c9c80892bf8d5c1bd31748d709bd653008fa98c392be7072f73b1f239afe8eac5927d7b71caaa79c9761de837fdb5c9bb6c72fe6bdff9179447e266cce87b32fcbc4a65c308f60cf41d77b27ffd131e69a49344b7acb3c5a44cb6815ada34db48d76d17bb48f3ea243f4191da353748ebea24b548e2ad15d548deea35af4103d464f513d28478da819b5a2e7a81d75a26ef412f5a27e923e885ea3b768188dc26e344e381be5a27cf25d48b8988eaef4a9ab701add249f52749b7cc77126f9788943364ed29311135d47b53888d39723e6e2f42181493c8d67f13c5ec4cb7815afe34de621895f165c4ffb95ed4a6df8dcec96a52573885b6f8bb7c93c7449f3f09ee35dfc1eefe38ff890cc9f8de0d56b079d64b424736b327afe9a9dfcfef7946d82f6d825f67f445b9dd8e46090fcade4ea7ef6f7b2fd7a1e090671ba527eebe693527c4cbcdeae774858715ac15ba5ed1ccd5cbbcf5dbb97113b629ec934fec4c66f3997a4ff9e51bef93f30d7fd953a9a67163fe4677abb79e4cffcbd7ff53bcb3d04d8aab9db87c57a503e3e25769036223ea7fb0e3687a436289fee757b5efc155fe2725c89efe26a7c1fd7fc5cfce00fe2c7f829aec78db819b7e2e7b81d77a261dc8d5fe25edc8f07f16bfc160fe3513c8eb3712ecec785b818a7cfdbddc6377129be0dbbe9b1988937f127c1249c4493f4ec681cdf4cd24f263dc8339946b79359184fe6934c3a42260bf79d8e9c78b24ce796a8e6e6acf429ff5572ed3a7a9c6c26dbc96ef23ed92776d24b7a77f8439cf2f76b35b2e1df763de1a033f9981c269f93e3e4148c26e7c95792e365529eece2f2a432b99b5427f793dae4c1cd2163daf03facffdf7e687fb106f896d96546dc772f310df342fe4ff31d5b3ba56d7c993c4e9e26f54963d28c8f93d6e479d20eba6e9e48e7c1816be7db4927f5b0927b4ea90f31e926a36499ca3149d7d57e6f1ef9decf1938b9d792937de45fee9f3fb4c78f6719fe47e711ef843d87f43b099f67b037de2bedc0dcec177ce2793a97d0b6a5eb1edb34cd3b4c7ac1383a4efa93c1e475f236194e4693f1243bc94df293c2a438b98a7293ebc9cda434b99d66a6ded49f065e769a74e9693c9d4ca7c9c8994e67e134f6d25e3d9d273dfc6a329f2e925112c7c95c315d26a3221d29f3309eaea2da6491cc13c98870bc0ee3744e49fe7695fc6d9eb0fb7b3a72a29b64d495a2abe926ca4db7d35d78ed3fa536339139b191ceb6febeddfad9ff655afc357d9feea71fd3c3f4737a9c9ea6e7e9d7f4322d27f3cacc7d5aaeae66c18073c03f328f680d47723df35b6b852517f3cc79ddf6cff34fe690acb771f794a695ccd3f46e5a9dde279f9a9b030fd3871ff6aa7406c2e2a9a44ffcfd3cf2dbf5d09f63933963d3ad8b47fe4a3cf657e791dd0f73fe6fe791ffe41ce26c28f6aadd9cf0367d9c3e6506d3bab79f3692ef266d91376d4d9b49cbbfd28695b037317d4efcf9743cdf24ff6e4f3bd36e104d5fa6bd697f3a98be4edfa6c3e9683a9e66a7b9693eae4d0bd3e274e05d4fafbc4e72fdf5f4665a9adece32332feecdfc59100d6761d84c3f61308b268bc4fe7bb378969e6e4de696f4cce8641ed566d3e493c432d1cd2c1949c99c12612e494745728f1b1d5132d7c4c9e8982d66cb49fafcf94deccf56b3f56c33dbce52dbb89ebd9bbffd67f1c84ffe711a83cdf6b38fd96196f892b3e3ec343bcfbe669759d95bcc2a2e0a4e3f99f4ccc0d467bcf387f5ff4bdb9cd671ba0e354c6207b7ffe3ce2aa5f5df4fedbec58cf93f5b5b4abca663dac6a94c491eb7d3a744cebb5975763fabcd1e668fb3a7597dd69835670f7e3c6b79fdd973125b7666ed59e22da631699affacfb87f348fe7b5ef3dc5e7832475fdc19ab1ce29e7fad7ffed01eff7fc523a94d4dd762121b327b99f566fdd960f63a7b9b0d935677e7aa129f7a361bcdc66e7e81ad99730d6b36cba67673969be5678559717635bb9e55a7ddd9cdac34bb4d0df1dc9f07f3a443cfe379322dccd33d8d85d749629ac4d79dcfe78bf972be0a3fe6ebf9269eceb7493cb399efe6eff3fdfc239d2726f1fce0e6826454242364e146479c7ebb11948e8a79324f6492f9a3947a59d1d5fc331d59613c5ba4232b9d63d29115c6f3e3fc143ccccff3aff925f1bba7f3d4df5e9b4ffef77b1ddff1c86f6d57e2b524f7a7f67136afccefe6d5f9fdbc96f43c3f896dc6f0f99d0f5ff85edff94bf3c8cffb33d9d4eb49e680e7f8387ff016691bcc1fa795f9d3bc3e6fa4f313d611ff8a9f90c1d984a4bde6cd648e4b4688d79db7e6cff3f6bc33ef2635fe32efcdfbf3c1fc75fe1616e7c3f9c86b7b87d4134bfc05c85ff95d59b36ece9c3b3fa3e0f46db39f2ce88ffc3be690bf8f0f7fbbaef5ab75e651e6b7fee09faf5dfdfdd8fcad6d1cccc7f3ec3c37cf87d7f3c2bc98f4ddabf9f5fc665e8a2ff3db697d91044c0b3ff3b408dc9ac84d66b70817d1225e4c16536f9f74f6a4c72ce68bc562e95f16abc5da2b4c0f8bcd621b3716bbc5fb62bff898be2c0ed1447bdfc9f72ef15d03efd5cb2f3e17898fb6384d868bf3e26b7159941795c5dda29ac42f01e20cce11737ed29191f4fc244e99c3fb4a6390d902f14afa77179378c9dc937a67494526a327b7b85fd4160f93f36c8fb596f89cb460ee776d79dee691fe2feabf94d8e44ea6376d24231e6b7b6e7fdfc510b82e89db9c8f3ff8d3f6f8f9ef05b6c95bfcb5785c3c2dea8bc6fc71d15cb416cff165d15e4c179dcc9bb3d35799dfdbaf706b5899c1a2eb2d162fb3eaa2b7e82f06fe79f1ba780b568be162b4182fb28bdc221fe5e26051089fc3eea2184f1757d16671bdb8599416b7d3e7593bb1689954ffdfc4233fcf2723ac7b7af7cba4132ffd65b00c67d965b4785cc6cbc91fccd3fff83edefc57fdd7cd23b2651a4317fa7d4bef4c7f74ccfd0dc407df7baa5ae32ed9f9a60befdf72af239d3fa6e9795bafb79c2e678be57cea7533afcbf972b15c2e57cbf572b3dc2e77cbf7e57ef9b1e82c0fcb4f9495fab7cbe3f2b43c2fbfbc56e2e377d2329797456f595e569677cbeaf27e595b3e2c1f974fcb7ab4593696a90d4bcbdd701d0d7a71bddff9f107b76fbe58b696cfcbf6b2b3ec2e5f96bdf48749276e54a471c7f71c92f6fe345e413c82390523268943bacb7e38459cb2282411fc743958be2edf96c379c5d9269c3bfea335a1c2efec8f7caf01ce28ff9cf3c685f5bce2bec09c76750a5bcb3d9513edfff7d9b5894b736b8436075d66f9e568395e6697b9657e59c8ec3335c438c93d17ed5da5652d8b49ac71862fc0f96792ce67de615e5e5e2daf9737cbd2f276955979e1e3caf75f43cf1f466f613d5d335c05512dba5985ab6815a62be7abd8cfad267edf7f5f4dfd797c5ccdbcb62b2febce615f7866dbcda18c89dc9a682243fabd5acd578bd572b59a7657ebd566b55ded56efec73dbc4e3dbb0ed57bc9eb27a13ebb7a8d739d32ef06dd8c7d37e3247d93fc44d33ce237d8c45e77b8e3257934ee68aeb10e9f9d60b6de2deed6deb7c925b0371bea03b139bfa8be9b5eedfb97435907f1f611d63b55f7dac0eabcfd571750a26abf3ea6b75595eafca61695549fe7db7aa6606a9bfbdba4f7ce380f7d4bcfdea61f5b87af2faabfaaab16aae5aabe7f974b25bb527afabceaabb7a59f516e7557f3558bdaede56c3c973e23164bc6a807356a93fdd71f10c6c6131b18b897d4ed7825623af3b7b588d57d9552ecaa66b59495c314fe30ace23364ae252ea51618424692e2e8157164e9211924d3cb6eb640ea9ce77abfcaab02afacfee1915d8a3fc1fee4d8f7ed89bf85ebb497dee4ff3bfd333cae92a7929b5a389cfefce1aafaebcb34bbf726b5b2e1648eb1f7b4e2ece18bb361ab875af740f1c6b5569fc779b795da5cf631f5737abd262bbba9db6dd733235b7fe98b46b347171c9659d49f34ccb4af2bf4fda7618a4fb1f97b5e7f5d7fe3a5887eb681d47c3b09dd6593a1ac2b95bff737595d81d7eaf93786f3d4d57ced7b3f57cbd582fd7abf57abd596f93d8e421f9dc79fbf5ce5bacdffd5912af74d7fbf5873f4d466198f62fe8eb62da974c7e7d48aefb5c1fd7a759757d4eaefd4aacef7d123ba57b6c2eeef58ee9596cefe4f661ae92fbf73fcca5e893d9242df95b6a3126e989a212e7b091f7eeeadd9d23f363cd273f9cd7d23c52a00f3d4aa43cb9358b743d7de5d6b277ee4c54ba4e9572d3edd9628d7b9eae6f24df2bc5206859d8a3f5617d5997fde1bab2be5b57c3ccfa3edaac6be16efdb07e5c3fadeb8b977563dd5cb7d6cfebf6bae3f5bd9e375b77d72fb3cdbab7eeaf07d3fefa75fdb6ccae87896fdb5a8fd6e375769d5be7d78575717db5be5edfac4bebdb4d66e36dfc4db0cc27b59ed8a7789b29cc5edc1c72e2d9dc915b9f4fe4fbffb87bb3366591a56bf8c770cea56559eaa18288080a8a967ac63c28f328bffecbc80487baebeeee7777f5eefd3d075cd6e0809019112b62c50a64b7c6da32348243686a7d73003ec12699df31c12708677077df41d9ed0e697f07944f5b5a688576e8846ee885fe75105ec22b2db4dfffcf6b0b90e7bfb4cf7bedaf88e8ae7e01fd2e67f82ec88f927a12b691681538ad2f715bbb889e8f735cd8163fd59ba2d656c281701abc260cc2308cc2384cf42de58629f9dc3023f947f4990ab573d930b74a84ebe03d218f06afdd844558fabbb00aebf01636e1349c99c7903194fbf5f29f7d6e7ba0203964c379c8858b900f97a110ae423194c275b809e55071ec701bee42d5afc37d78083fc363780acf61cf3f58b103fd1c90c322710d9c031c6ad877594ff22f2d874e019e37e4fa30078170b61d1d6a4b01f6a95d0e0fe75031672fbed7413ccc0f207e24b2b7c8674e5bbe01b947c887bef0b5089f2a0d0bd847f61a79427c56f43bce37215b82f6e11ce7a886d4947e0bdfee7bf28d823a07798fe14bdc0b798f39750b076668c9261fbe87c3f0231c85e37012d15a5f2f232ad2223d322233b2223b72cc508bfc4be4469e2d3a66e49b6174719ae81a055168ab5114c5411d2551aaf5a32ccaa3222aa3caec4775748b9a681acd2226628335e4e8a33946b9c47ec45d6c4d78bf11e748f441577c255a447cb4d46f8668d8c8f63928ba6af1c7c39760bce291c31c4642b442b6d132cf8618899114ada34d24470b6743f991d2d61d3accd1ebfa52bec1055fe3df47fd82f4ad9c9efcc198f08cf17b0e706fe49e56b1ad43ffb315ccae247c06920322f78170b2200f66d013d3a2e8681bed22155dd37d7470a7700d6899a290df65c1fec23542cff98c8ed1c9c8a373d48bfa9412bd39b2c64683e83d1a461fd1281a1bbccfa2ebe542f5d5f05ce7d9f77696e4e14ba2494cc7947984ec398a5071163db40c25d6d0eeda9b47fda61d63dde0030b3d1a86189b261f5bb11d3b8118bb9aab398e8c708faa39b117fbe8b8447220c7d73888c3388ae33889d338a3ad20d52cf03d90a3736377837c8ce2ac5f3973c011a7fbface3471acb247f1128d7d34e4c8b6718e7d50dd72a261ddd47181fd0889df499d1572491b478bcbb842675369725cc737b46b26503725b55dd2eb87f1c100b8491a8ff62c7a2df2c4b027d123dad3e83dc076e1e7a3bd1a37f1349ec58c798d546de4e4316b24f13ce6d055591882e518bc41b9a67132fb311f2f63215ec5a2cbc652bc8e37b11c2bce2ddec6bb588df71a4b29f121fe0cfae8f7637c8acf9613f7e0ca5a5adc8fdffcf77810bfc7c3f8231ec5632b6af152d4d668705c8bbebdd1e649dc7872a9123aa1122dd113c3828a628b4fee77fd81e621caa2ae4662da703b94cb24b1123b71a28fc44dbcc46f6bc8e193ff707eeb4bbec323bd174e828ded207e2ee0316701b92064b9b09dd7584746d7788f7e6f6b2670edeffea38bb9010f5eac0a3fa25d945c12040e92c0a992d03d438d5e5bbcf4c46c92288993c4721264852ea324d312334cf2a4484a834faaa40ed71736b9250db22a0a8eacecae9ef4e443fc67fc86eb4c9657d8e8800a2eba76adaf463b05ea550adc37d82dc07148a638d7e8988b649630099bcc132e59247cb24c8464e5de12319192353a970d3ae44449b68083925da29a74b24f0ec9a723535b974d8e2e0b3c6ddc4b347e60bb16d335adaf801c59c7b3b3e9f88513ed602cb66af95ab876e98814b2ab2e979c9273d24bfac95bc027032f8ecec97b324c3e8275324ac6ba994c523ace520ace22d0607f437e9d52528d4a531dc597318a5729974b0d974dcdd472d6949adafe25387bebd449ddcb8731d1fba9972c523fbda4d73448c33432fb696c2889013e214d92619aa2c865efce352bcdd2dc9a99615a68fdb44cabb47666c132bda54d3a4d672913f329abdf2c279da79c5ea3c78576b4e4944f97a990ae523195d2b52358f0cdcb748363db3295d17706fe2ff225a9926ee334dda5aac9a77bb43f7440ea5d3cdded8e6e87d8866b5f21afe5a587f4333da6a7f49cf6d0e7f4d3376f0cfd89c4d6d37f9c1b7cc623afbee4ed09a3bc9108c9dda403740ddf69211da61f41908ed2f1b5974e325a77332ad3342b3901f7b8f59b8443c5d1a467b2c38bbb0e9f657a6638fbccb485ccd2b5cc46f73d45d80fee9f1f509993b9061f9b869579991f1eb24b5a98c7ec9a0559082b1afd1c65719618c245051f1bada0aa0ac7ebeee8ae5f8bdf3c9c2d6fff6e4e5aee826320f003dcba2c453fdbe610ed2003b80fb0832e3b33ccb22ccfd0e75f76da31d96465566987ac36796010c1f3215b021979c3d78ed92d6bb26936cb988c8d2ca38c3eb279c6810f74e40ce11e5f813c1cf818a8d3e88a8bfc4ec6a3359ce0ff2b997631706f7ee7cf5984c55657acb3d2e60020eeccb36526642b03adb8abe59ac05fb290f7cb44740692e584ef06aff50c3ebb7971b2ced6e8ac36991c6c3225db66bb4ccdf6a6941db24f2dcb8ed9293b67bdac7f99666fd9c073b2f76c982cb28f6ce4c4f6211b67936ca5bd69fd9c46df766d69396d3939a5b3b966f28696eb0857e460f34d37377233b7723b777237f7723fbfe4d73c407e6e95877994c77992a77996e7ded116033d2ff232afd07bd1869289e631aff35b2ae58de96a4be43b429217caa7d8eff55afc34ce67519433396b1ebdbccb67913bfb6a13b1ad04dbe7c53d934fd27c9e73e83b2c723e5f5e132a46982cfecb39f90e8f7cf5251d3fa9aba92bb990af723197f275bec965433024f4bd1493cfb739f2adb91a3bf99eda0687fc80ec66c7353e61bfcea3efbcb9f762227b093102f23f0a3ad4fcd365f3637e021c904ef273decb9679ffba4806288afa3094fc2d1fe4ef9a9a0fcd3047bf27d37c948f4d2e9f14b461a2950eabf98de4021ff8ed97c373dd977a537b5dd17ddfa0d75de1b1a09c2bf01fc8f3e0fae29ce1d950e0efb063aebaa118be21161af14bc08dc0381157700da5d00d01ed9e6361a0f773cd7e8122b6c2cafcc22e9ceb67226851e11aef8517d78154f8f9b9b8049be89c9d733bcde07fc5b5089c2da584459b5b23fe3cbc602d23ccbf8d29eeda146111157191a04f4c01c142f5acb50f66cbbc40676d6c5cb3c8ee8f624e7971911745382ecaa2d2d4a2463b68a31df41bdaef0b74d6b77c5334289a5a187c312d660513d6e8ccd9625e70c5a2e08b6521186ab12ac4424af2625d6c0ab9508aadc75369b12b54eb54ec938fe2507c16e8bd8a53712e7a45df99176ffea51814ef86560c8b0fcd45f6d0376d972d46c1ba18eb8d6b40aec5e48a49499794553a1b7a1fbe61fe29177154536a38678739a8a55e1aa5595a971dd4d1c196e13bd9d64a1eb92d147f2b975d6903962a518458baa557fae525285a6d905ecb1f3a3ff986effa33bee291474f1cd87b9c8fd24c8405e6e5b50c8ab80ccb0845a50ae490cc11b2dd23db2a634b2b13932fd3320ba625c20f65611fcbd266114e819acb7b595d742a45b13c8acb35377d77b9b2a685f25636978db3f39b400e96e5b498eb5584ac8af666d4e5ac644ab69c979c390cd964e74fcb45c997cb52285766cfa6033b1fe18aab635b91807d05f6b3249fd5d699bee09147cde9c927b78fb07b601d95225e5f0ef95f29e15c998ddeefd9a73fb2f28635727c17c2bc51b9ee2c19610601a32831e1fa203fc3c1ae8944ed006bd41f6a2a649ecb4d29978a1940b48670155f6ed1df76c5a9548b416e96fbe77e2084d38a7b7d24a2c7e5c116cbcff2886251c31f00a38f30f9c8be2f4f5d850d9fe9d3a3e1946782be906d3d92bd8c7eef11ce2cda695ceb19fbc6ca72f429c4b5e8cea2e796fdf2ad1c94efe5b0fcc8eb72548ecb49cc557445555aa55786f15e999555d9a55239e9d1102bd7505ca3f220a22ae5cb32b735845f4cbef2f50bb5c5755752171950fbea62d499843e57b6b4ea5a05c1a40aab88f20127215c95b6361bd761aab84aaab4caaa1c7234c4d695275c73c70c46f01d70c50bf46331ad8a7097c455595555ad2ba1013517c89fb4d8e17cd76679c4b97f8647c83937f79f4f087fe49452ddec895169fd2b8adb81655935109d985c3545361406d08fcd7e30d38ed5cce023744d2ac672a2ac62abb915b7b872e49815572d2abe5aa68e3ed2fa9590ecaa95197891c95f114aae90af4536d8a92403e13ae89331b46a0d9d00e87f9ba0a8e40ae1856a5bed2a3531008380cfb0ef58e38593e07fe747daff3f67d45f0e608656fbd75cd893efa6ec2f7f6fff463dfe47f063e7ffd1753a90ac0bf828b0e2856688d104dddb37d891f877589f22f24d22f24d42f5a9a168ce3c5647f49d4fd5d9faac7a559fda134c8df1481fed97358a49e7d55b35a8deaba1b18738cfbea0386f534af7b8d2bfe72c1e7502882b315716f76ce0bd6b60fe2cd85e38ebc474e0bd901faa3eaa51b5f2d46a8cce64624e6a145d0596191653adaf9db5634dd55a88ee388a851573a11dfc21dafb28fa8148afd603a6463b17af60dbd26ab3b66abb766ab7f66abfbe54372a455145494da922ddd0c374101deb6b1da03b3a41cf0deba88eeba44eebacceeb22c8ea1276545737a9abbaae6f7553879504dfcbf5ca936b828d238c78b4628ec87323f45a4feb59cda414c4af388722b7793cd05b3950be2bb96c68f897e4e4c8614ea5eeccddfc52ebfe8247082f0a672e39b2531c29762f4e64d46c8c22087437f1f54ca6e87bcfb115ea5753e2eb0c13d960aee6ea45cdd74bed88ce91bfd26618d7b51068995a8cc38f7a553215c29585657850a7305c43ace78662235c558bb504f78bf84a7382ef1fb2e16950af8b65ead79ba244f703ed18f477c910a133a0f3adf755fbedce78d4471e8ff6e3117c03d53ea2f554cbddff3b5ff4f4fc97cf00ae36c6855daed1ba9f0fda21b5d2c600542901e70e59f696a30dcfc7d97da3dd5d1db702769307b9b69aaeb7496a086961f0f5ce146bb5ded7077b0d7ba4fea44f9e501febd355adcf75afeed76f955a0fc0f3619ed2d3956863c97b7cde1d6d4ea38b4b5ff84ee8d3dfeb61fd518fea713db9d137eaa6dd90b93227650cfbd83c427d02e2cd9b09758afb5e17a209f2416362c3cdf1cdbaa1bb7a736eeecdbbf99673bbe8f1ed7a0b6ee12d825cc52da656b784aaf59d26dfd208ed44dbbf65e8fd8eb7fc56dcca5b75ab29e576bb359444cfef36fe4c7956739b46e16d766350f03beea22c6c01ac1bb29d4572636ff31b97f76f0b6a47ec0bda916ecb796de8b333bbf1ba7e5bde38637013c251368cceb755c6dfc45fb4a57ec52351cb61257d8612f24b5b47be49b7f56d6338f91823d8611aa16f2cdf94627cdb22cbc111ee714c3b576437258bb9ed6eea6daf5f82258ab3d9dbc1b16f9fa91f4a805bb08fefc34ab0b14f041b8a563bcec2de8edd7d6b6d6f00f1fded743bdf7ab7bee1840c7afe99d86a0bb8cf17e3e97e7f8b3fbe1c687de8b6959864ad743943bcaedaf7b1e86aff58378f35d5f9a9dbdbf37a7aca39b6ffc3fd3de3bbbf014e377efe6d606b6d5e0de39bdb80dc531249776bd99cdcded13144d7f7e336ba8d11f6aa0cfe36d1fa0ddd5045047ba4d128aed11ba331cdb0b1bcb8b1b543e398c706d87d543eba63117485485cfef011f0ed1fb6e2be9b9e724106f63135ad1d1baff1ad65730938ed68ac6d2db013b3f50b63c8f8b5b6057d2bccc94536c0a651c433b44dcc871ada7a7345f65433f74da0cf9bb089b4ac899ba4491d097ada9bacc99ba22993aca97ce41410fe114d14af6662736b9a66dacc9aaa61dc4daad1139a83bc3870a1c0fed37baad7b0cdbce1021467bb3e7c2e3a07b4bb9b45c337cb46685629157d52aa3ba352e09cd2db966f8a79538dd848cdbad93472a368c051e29b2dba8e3bdf6ad4a7fe91dfe19131c541ef0cae7b9c352b7d6ff6cd21d965a2356e3e6f3877646c2ca7395a7bffd49c9a73be35f786d5f40cafe9bb5ead9893e6ad19586fcd7bd26b86b1d07c9429bac612c986d81782a76085032313560ce91a83d5d58c1ef880d86eafc07d310ad48b9ab1e31b6d5f4d75c809379a7af221def3fdff03dfa1dbafbf7f89aa9a0959edc83a3e3defb10b1ebeebe9f5ed2ec1533e47f7f7f3c07fc0417025ac2782186e03bc6e35ec43ee119c399cd2f918bd5e9c52536d8aa0c0d44ccb298a6fa6f6d469565397e4b530e36430f5a88fa93fbdb8b7e9751a4c4343c491c608f2d5049be0bd6a7636a5b50dfad7f8b28bc6da476a1a355773126bda51eb19f414f90e642bb45a41bb0f7947d81dc4777431a66bdede5c739a002620680f6c80e14ed36936cd114a3dea3cd461a7c5b49c56d37a7af377d326bc421c4f5b613a9d4e6753c65c4fd9e9dcd2a61c3a165a7fca4f97b7657020dc597ad5fa10cc9d453ec19b0acd65ba4277c3361c175028b235b7e1549c4ad335f21b9be986f4b7a0e7423d01708c830f529b76ad662a4f157465b79633dda147d51d4ef77f098f34ed017d877b6aabc9d3c3f433ab918d37507c8daeaf73d50ed3e3f4942ca7e7696fda9fbee108b08bcd35845394e960fa5e54d361bd997e4c47b8a7d202dce015088fa16bdc71966f03623b496ddcb0b214dbea21be17a47f46711d6215c1d7e3ceb331390f627f3b1c405effe77ee4b19a5f7089ffbcca91df7a43ab746c88b0237eadd57fc121deafbee8c9422b24826ad722743638f811eeebe3f9a46f68389dcce81935d30a29ac2ec3e070755df622cdf4489e1933136a2ca43ea2abc88eed6716a5ceec9993f50c76866256a8a142af1ece6f41bf046d5bddaec1fd1670d5f4e7bd4df0c9e391e0965a9979f03c13a1f46832f3d1df34c889805d03846f229b6d9e482480bc23c23dc48f10e48c6c028a98e08ece2eb3ebed6316a4e7f25363117e6a6661f4119d2e9c319c45b3789650b4afb8ec75e9b2b3547383cf5936cbcd7eaecd8af09c0c67e5ac0a6e60af757556538d55b57568a869bc3bd2ec366b72ca1031fbdd2b25c3450838f7171e0f3e47dfddfb29483d1bf757d063dc87f186b0c8a13ecca6cd6a364bcb193363834370c3bd0e6f7f561f217c5eca875a72f4eed7ba309bd734d8fc720d36efb2d3fac578c6cd1633be282dc0467d633d5b969cc921b030018c119be631ffd0fa33c1c4780e61490e1fc037a3c1ff9338dea2dc0b8e4028926935ecd90a2c12c404b582112fbafe314df24436c4f20e603adcabd9ad58b0cdd4579cf03b5ff2145774f9adaf111abadf9d1f79f88ce775d4ae2fca7ee098675cf3127de1d76a2d3e76804f07b948723de0bb90cf34bbffa3758522d77026cea450bf1898a77da2f71a7a0b743f10dea468ec47da3e3f970d96b3f50c6181343470a7aaf9d41f81eb0210d75dc999747bb78b4bbf72639faf1078d06aea0fd05979d38cc4b4717f2627f94c996d67bb993adbcf0eb0136c0dbd4f974924d9e731ec4a7388f00a3ffb9c1db5c0655b8ee806dbdd9c3a7479246a373be9d7d9b9d2673d4705d65b7c9df5eb53359fbd25d7f200f502c2e7a16fc0416b7101f8850bf43fcc06e8fbbf1b0a7c5e9169c7d970f641e55057c1b8c3beeb94603e41db774ef8600dd101d615f43795dae90aba9ee7b6aeffe77cadd36c145ef355c4cfc6d5cc3c829a04ae1ba088a172c39bb59c4df24f86662883af5c40d6c8c70f19ad10199d31d01d47889c31198bb1cd23836e10e3929c8eeb90b81bdb54ca1fc0eaeee2f616f729d38c6080c4045f4156ec3469f396d80e8385449ff161288c17b7999be798e1ebe33778e40f7d0cc96be1f3a2be721cbef99c679ff49cf77aca9b59237f50a3fb981559c9f8a091c35c982b13405ddffcc096de31df907546d1381332515a32f1f5c824f412f387a15fd66b79ce5dff480fed1764c7a625933299e538a1396172ec3b0cb035b053a02e92184c911eaa6d3033846006f915438403f90011f62bc96b11fc71e7caa22bce94e017f03eb6628da98025cdd4cc2d1c320d336566d6bb76601874c63d1241c0de7ee45a001f58385e64d8a9e932983f46b79c4e2e82feb53eb2e915ae49abc944538b29e4fad16344f5c33ebd0f0ae00f3073376ef59f0003ac09b70cfc67cb92e6184eb3980503751c11459a3cb364042bc15110e9c786d78ddade6fdc774efa62303ec1ba1f1d478d4a9915d63779239cd52f35f7d3173c825ee32d19919198758aaebdb106ff1a3060df194f3b963eb36164cd4d878c125880134caeb8d56766cbec18645d1884c89903f3c91c99538d6c3e73cec78035989e6b927a4a7b2f4c6b8c7c08c9e9f8e49e9a3da6ff72cf70fc0f11cfbda671b7bb17d5e4a2c9c3c7bff88aaf59db97c727bedb4b16981c45e69ab58c7ed63b7c7b7f4efb394fe7e24336b75d1ffef33a839d862b0c3837178acc5ba95c46cc206399f7f08319321f5981b3171cf85ca88b30a362cc8c994910514ad8a77c96662956837bd6aea7966f87fd888bf3f1327a96ce1aac6939ac059d3196761b9a1cf0692c03edc92b6beb39ebb02eeb5ddf589f91d80b7b35433600de8c76cc4443841c08bc8e0d21176558571dadfcb321428e1a3c1ed44dd808bf9fc3c66c12aed9748a6ca3763204d780fa0ace5b436d156b92b4b6ce31c7f8f3336add72ae4ef7de10afad7138585f452e5cc867c1fb251b4d65d1f95a33b4ab4ec8fe57c0d86fb5df635a68fb1436f73e01c2e5813e97b7dc740ed75da8b1c55d93defd0bc7ef9ee7b59804fa30802bed815f02dfcd96448f8b1e5c13b6626b0fed904a02de9921348e21405d593bb337b6217c57768a8248b8d34b9631de58969db31cbb60797689ee83c09aec0a678a1d52bb267581472d9bfc1d2c105969e8ffe87e8402f159f87ab7af238fe47518b7dcfffe78bfc7dffff8f1fe3c177d265a0f90c72c745c0d75708e6d04e7c1622b4bea68f7f378fa1e6407403d03e73a3f882e81897c450d99873760ab987d165d3b766df69151be62bed68eddb072f819abacc26ecd305db23b569df6d93d7b8895cb1b955b657ec0da35b8078afd6c7b563acedbbd7f843d6a1c7b62cf75c9f67c2b1ab2fd621070ec1b3b60df8b253b347aec073b62c7b6ca4eb47a4ecfa9b9765dcff5b9914a73736e9962bd2a2ae3ad8eacadd19bdb7367eedefa73cf9accfdf9657e35f479808eb05806aea1cea379ccf4e7c93c9d67f3bcd6e745b19c97e67c5ecdeb7985fe1f4eb3f96d7e99add06b6ff07a74046c346ff4c17c4a6bf3d9aca6eb39c39e238e8ee7ec7c3ee7e68b394f2de8f5c5982f99f15c08dcf96a2ecea5f97abe99cbb3fe5c713ee6dbf9eecab8bbb97aa1e67bda9e1fe69ff0bd6986f6690af9150466905dbfd0de9c991fe7a7f979de9b7fba273a86bfb360f3ffd3478dd25c05bd6f7ffe361fa0737f9f0fe71fe8f7d17cec2aec199ddb845e723447711a3be074ceb0867309810d8bb30d9d73ac23e772defce8f3a935b7ae6a62993746e37cee92e4f13b77e5022e0c58cee1222e46af49d06bd2f985cbe0bab58fe83a72395774bf37a36602f705ee07573e9effcf3c3613ae0a392ee30a2ebd9db91a7faecee5705ed6a496b82270b91b577305534d33fcf7a0bdfff87cd1776ad07b4cd3607ee3661c83d648ceb1dc9ce3a61fe1d860b805c733e3696f36e496acca09ce915b79334eac4bb414b7b7c079e7a4eb1bb7e636a9a46d38b9bc700ab77578caa2636ec7a9e83e35e8fea0fbcfed69edb10ef0233a081e6935120197805689cf1d667ab0e43ed1f53f722733bcd5dcd9931c9d23da4636f045f53dc4dc98bbaf72fdc22b22ee8ded7303ee1d450789a595b18d3008b65716b101906b3139c023e0111907f913ccf9348fdc90fbe046dc3814c2253769b37963f23aec83902f5ad0d97941d1938546faec4c17638b4bdb6701bcd6c6d116fa656a089093825c5cc89afd85b13067e542afd385b5b0178ec7229c202f1e7d975f754b7af4043d1eda9ee9eeef7fc58ffcee20b9b098e09685b7f0eb63dbb3a9b51c6a89da70dee2b2407ed9da2f82456839c89758866cf68351aecf75dc8be32e22ffd208999f8996b388b1ed3ce60af860747d12b0c3c83e7799fa31897cbbeb688eb18e187ec4518949d02c57b43f8fffa947a8e0591ae9cf21bd9e100dc17a68cfcf3107b7135e1f67a893ddffde3ecf5016a9e178793e5a64fe0070515a2cf2405e1497e1a2bc6617c75d5dd6d04bb2a816b52dba03dfa1f68b1ba55617b65e34e85a4d17b305e3e8c0c56a670a60fd1d882b3a1d4c7cafb4effaf75b5d14dcaf80fb41b0ee1295661aa5eafe822dc666881ee70bce652f3695769a7910afa1e7d1c091d26c7bbd58506ad42f8d385df0357bdb1a477f00b92f73f4c871e01aae3cbfc10eb14657c376101eb731431ab3d50c40f76e97b933eeac37c875e3daf06eb1b445ffa23994aa99f7fe67dcc382753c747a9f0b0b41fb44a87f0499656b5c72e80aadd0ba13f56a21a11db35e6cf2033a5f19624e8421fa4f3ddba4eefe86f952d04b78809e78aabcf709fe8707ce7ff5713da65928d460b15dec1c01eafbc866819ebd41d1a01352958bdd42b5cee87aefb92b3ad7833f88f9d25b7c425f8a236966e42d8e95be38195625911d04b99ab68f037a331c60a9741c07f2d8e10912f59083c4f270ed6b7a1e60bcd9fefd9f7a845c13d45702fb713edd7d86f398b61883bce6f9203b19d7cfd0ba49f7861239d74f5ba414cda4e8c599f2173d5028227d208ee66ed0f5f4b3c5f51c1e8a31d48916fdc5db02cf9d69d70cd6fcc2dc06ee9e6bec636cd93ce905bcf6b363ddbe56539dc4fbe86e526b2b5dbc175e3271e40583794efe535f42a7c50b7d721ed6791ae33dea5fddc570f1e1c535dde6289e7835b8a63a6975ac745cd3c67cae8eff65bee18e9da71c06c9b958d8a658dad55a8c6a7b315e4c783aae28bfedb7f3705f5e4d5d753938f014af41ee0db3da4c93072635302f2c8ad4cc2b9fd7a92d6f20db8d35e4a147e04907a39d9342f257f719557fe768757bb1df38f3266ff136eff0aec75136c2230ec148e8fa215c7491788ff7f94bb6e3af7c60f27cc847d51cf9eb0038c07c7ce1f9844ff92cc7be017aea319b9c706f2fe604f3a89eb84c5d6dfbae5c317e45d860ebe797ef72533fffd8ee14cbc5681bffbdab34a3efc2e738e3631a6dddc37e79f4f2abc19cd15a71bcb892f9822f2905e7327bee99e045be02ce755b63da2c6e7ccddf700e908b35741d9b4b83fdc7a9f5235d9f0de92d7af88c4e43ffe51e12de2fd6462ae9d37508be44dff3536ec7cf52e52a8586cb3a6b9e011e24e46f70ffd6892ab16d3cc32c28acbb8a7b12813b0cfde2e8a4587ece73c0c962ce8f5c05ce57219371f72db82a057977d2478e19d4c03ef0da2bd8e5d6bd7ce4daa49a652234ce2f78de68f86585bc29ee337b871c92ae82ff4b4ebc8090abd7f27a26e8aa7bfccae8f2eb9a8d223c5ee4a5aa4657f91df91292777ad5fe38b9495b0b7fb3aa7656c8dfd5931d503470b97c9f5f2fa6fc86972905f992069f7700b51a646d544a31d71e35337985df166ffc8e575997df9b36f86a4acd4d332c13fec09c1d1fd8e08c07954ee00043ce8ad48e71ddeace836a7f6feb0b8f7c63773f20ea9dad88d6cb173ed54f3e9ae4fc1022ef13f63bbec774b74b603d3413e2375e7d6077deb6c5a0282c13f94f7fea8a9aa3599444b41ee1dab66baf847e7e74ef36b4aab9fcd18b2d1d572f94a8e24fd4c774035d66ae0c3c09a2f788f5004e440f8026bac3cd771a5f6d3f3bc4f36d8f3455f1677ac9f7f8beb3c05333c91c8e4ee3dbb9fb911eee7b83d7e21ee030837a03e86f68fc82e1df920f7ee0789676f7251e64155d737e697b0468609910df023c1a525fb965f8ef2f7e04e7f827d0c786190311c9912d926b3fb2728f7fe787d43be0247ac27f5c3ef81130500c8b1ff3939b9d8f08af0998dce4ee201fa3e8d3256d83fa410fd7c99ffb063b0d11d2533e683562fe9e7e53847be70beeac8bb9b5a4969a259ae152a77cf784f35b9d1ea21b1a4b230f8343a03972f4ce1745349bf0a55546d0e7612ecd2241f1bae9f8013042701d03f8686db5cf831c511a927ad6734de2e1c7ad96d3dcf5c680d542f8f0c9d7fc0307958f20562874cb595aa5bcb48167d19e07611da1f3e7f3878ffb95b78177f369e92cdd787591bafe9856d76b8a7385611bdbe09997d476e92d412dd03684e5c50c9dadb3585ea94e5b06c73e78ad13fd85e7f923dfcc1d6bfbd9dfeef5dea3ada0b87e870f83269adda7968f8ab54f5a9bdb69f461edd8b6f7aed3ae3d3992bbd6dc65b00c9711dcb98e63097e64190357f55105ea389cb70c74ae302feb898f03887d9968476c7f80d7e3c26bc166e25e0e11a1567e992e3357a2f7cbfc7a2e18f388a22a1a7ade96c5b2243e0c344f902df2109a27eaa35c39e4df97555d507aab2109dfe969762d9e87d8fb4d8dfc3fd024d70f75b6accd309297b765d334cba93348861460a85dabd592bad2c559ce968cf5994e3265c92ee74b0e3d2e169325bf5c2e0563611e0dbbe5ae769d091ef090c8ea729f7bca7fad4f588f7a46a7ed023592e5ea1ff521e871292626ba57c2525aae196db9998e3bf6cb9d5361e1fa88f7f01dafef83beefc5d098d3525e2afea4d8a2f84160e6cb2deebf2fe96e6ec93b9957ac99b1b744eb02b8ca4b75b99f968b08eb4f9edb99302a59a70f4d7bec8f8668fd437579ff1b3ff27b1bd8f564bdf65a3feb0d3e748b5e66d952f9f2106f969f866628503bc7b6c0ec5807cfbbe4a996dade59e87bc67ca02bfa96c7e56979d6fa067ebeebdded20e85e5da182691e176b47a67694b2ec193c2058e70a8c44623fefbc1d1f7c104190e97ed95fbe69fde5206852a59d7f38686bab832fdfefef1f5e232edf59d33c2e8785b7fc588e96e3e544a00504c551c4d7d9be8fca7003411374ed28a0afd6bcf1fc5c3004e8a5343f4153463b16fa73af46e7638d2e32f59efece811203ba3e98e183b90ab4ddf19bdaca1cc93d113cf2acd4f0d307e04ec33328c14cac602a58da01b8ca8ffa78db3ff2c25079c6338447666cb483600b8ee06a7dee9dcd048fcc1da03b3db56efd9d0113071bedcd3c0abe7011ae18473f7486bfea663ef0c7abbec0abde6f978379e847bcdd7b2b54bcaf7e9d31f45d0ea7d5eeebf4c71d91a28580e18510578cac34823c95103d756775b8e1a5664bf219d8a7a0ab27c44222a45ed2e541307f0cef10b8d3086f88c6da14842c3908b950082566be78c0a600dd5e63e35ef02eb16d3a9a04cc4545ffb70d679e987da1d28ee9841ad107f07d4473891e113db1fbf13ccfef3f7c041d32ad116ae1668642e3b2c214f993caec4fb7d73761368b7dc55e098cc01a9ae5401f39d4d9eb77e01cb898c5d3d5bf8bece9badd7bfbbaebf7aa35d9b2c33daf00be5b1759bdec069225e909f3affcba9f7d34ac32369cc410386121f01a56a7031e195af70f16890778e45b6eaf77e7e8426ed3c32a4fa1b0b40782501fac08b4e0eefa01db6e9e32323e11bad62b762c882e779fb3f53c53ec9937f7e03ffc916efccb6cbaa79a41b7f75e6deaebecf353ab0578be3fbf9b5984edb22069fd18d74780a56d5bc2faabbde8721846cbfb825c8d81d974c02712362125c88282fbcc311b12987e6405003ec1b97ec97284adb0633e4ddefc803e67882402660ab9f70f58658e0fb9a0faddd2bc9c3fd4a2a026557d16f68557d6a08d017927ac73e8fd32d7f5effb11d75b0987782a7ce6c2f2201c8593b0e73401f946ff2cf4f83290b291b531559ccd9d405dc71cb926e0a62e43fa0beff5c9072766f7f7ce72801f7e589b674e6cdb797def2785eb7b3b3f47653fffe804425f781306c2bb79840eb1ca6d59b12d97d8c2751461f84ddfd1b3bf241876e40f04747f8591301626ee00787b5877fed1af6f639c3ca6d478baa28b08f7f7136edcabe6d9f3faedfcc6ebfc91d7fac85d4be31bbff0dc97ddf18cd4d6beb6fbf33e0b90e482486d01b403a754b9a256da4a5f192b13f85e08c18f566dcea5b55ddff8908e5b0c3f8796c9e7d4ca5e392dcfc826391bb8bbb03b3a5e91b159b9ec2a2bd3b8eb4737ac15c21fc6e696411fe1ca07351aede8a33b15555a9f19af2eab6b335b05f5de4da96615028f17ebfc15bff8ccbfa99d0f1af6c54e731d0172faab68aaafe2e8b44aac7d3089d855aa8f78de58dfacc0cec736fe9e8605fc57a80bb55803ecb2562bae552bb81fe2de674ffabddbdebaa7dc15f85ae0b9619cd75edfae3e627b6d7f05f623088f3c7a7dfe8903b42cf13424e0eb619fae937ef37bffd1b31ff9b56bcbbbbdd501e6039b89b9cad07dcdc3e1aa5895be807560865ffcc41be4b61c71165ee7ad36dcb3fef1579ff33c7f64fba7f347ced4b3eff855afe3f5ffaf7e85d44a3a5da24e9f1162c486ea4d6fab6a555b6b435cddc08fd88ffee35f39c2f79f89263b891a568d4d749c02b4e247e6e4e660659923e4bf01e583d63ba8dae478820e7e7f607f2be6d9f04216bd7eaa57abd98a094db631de17e565b862b9fe9475e9d59c7fbf8598478cf3249067bffb90e867fc08e6c20147d9a60277eb2d57dc6a7171fcc38ae72e97b1509ac704fa34d06a5f2da1e7f08eba119ec01d41bfe4793a1fdcf6f1dcb9bcb86fb4c51d242225c7437b12fb67c2c526fc27a5c523ffdc817020f4c1f32bdb5a09fc04d4fb5e7b123b3cf2f021d6f8e5f51eec10a2f16f4eb4b3a6ae56d6193a02eb034c67f8b23ebb99572d076ba1bdcc8effea475e75fc7f8f47beea406d5becfffcf7f39763f0f2fc7b8dfa49bb7688fbeadee9fd4acce895c45d56eb3ab4a8d5e6de73f8d21ff0128f6ac051edd40270975741ae16f6333ada0dee4a2e4a5e8b498f2207391de8a5809c16bc1fe94381bc0dda21ca6abbda314d76d0ae2b95f2811bb0da6bc2eab0fab4dcd531baae4ed467379ff1ee3f7ec55fffe9e309cf0ae168d24995069fabf3aab7ea476366a801f716451058c5814251a44de278e8c3867a51243c7cc41d47786d2fe0dd7740071c5c0712a19ab8dfb0cd11b63d83b89fa2ebd7f33b9f0d7ea49648e6f88f7a09ffce239e25a9a0fbe7d8a6e32f45d7fadaff01e784f35abfc323786d10dd0443b69cd59bc7547ddf8ba5d5e0620373e865fd92fb36d6d53003fd50fdcf34f51ff7f8791ecc573ff23ccbdc7ed9475d1eabd3d17ecc237a7ede8bb620dea3033cd3b069e72e297cb97ab7d5d570f561f65723d28ff0da07f0ec43b042d9dd66425d04ed18adc8621a45564aa1d75661afc68b77974de6ab8948bba64810fc2499624ea8256ac4e7c4e851d445a3fa10cde62c5abea52b58afb1126dd1115dd1ab58d1172fcd46ec748abd2fdfff27f04884af43806ddac5aac4400c6752e95a8e18615b6e41e4c378c42792de4b5cc7f1ba3eec76ce09f7920bbcf702e20a2caebb13ae2d46b7b813b7b5422d2e203ea4c37b98530dd98b7b9dfdcf6be5ffd923447bd0e1007d805d1dec19afc0b9433f7b1b257ea9b1138b07df0bb47a10+ + signalTz(const QString &, const QString &) + + + diff --git a/core/settings/citytime/zonemap.h b/core/settings/citytime/zonemap.h new file mode 100644 index 0000000..c9c2035 --- a/dev/null +++ b/core/settings/citytime/zonemap.h @@ -0,0 +1,157 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef ZONEMAP_H +#define ZONEMAP_H + +#include "stylusnormalizer.h" + +#include +#include +#include + +extern const int iCITYOFFSET; + +class QImage; +class QComboBox; +class QLabel; +class QTimer; +class QToolButton; + + + +class ZoneField +{ +public: + ZoneField( const QString & ); + void showStructure( void ) const; + inline int x( void ) const { return _x; }; + inline int y( void ) const { return _y; }; + + inline QString city( void ) const { return strCity; }; + inline QString country( void ) const { return strCountry; }; + inline QString code( void ) const { return strCountryCode; }; +private: + int _x; + int _y; + QString strCountryCode; + QString strCountry; + QString strCity; +}; + +class ZoneMap : public QScrollView +{ + Q_OBJECT +public: + ZoneMap( QWidget *parent = 0, const char *name = 0 ); + ~ZoneMap(); + void showZones( void ) const; + // convert between the pixels on the image and the coordinates in the + // database + inline bool zoneToWin( int zoneX, int zoneY, int &winX, int &winY ) const; + inline bool winToZone( int winX, int winY, int &zoneX, int &zoneY ) const; + +public slots: + void slotZoom( bool setZoom ); + void slotIllum( bool setIllum ); + void slotUpdate( void ); + void slotRedraw( void ); + void slotFindCity( const QPoint &pos ); // Find the closest city + void changeClock( bool ); + +signals: + void signalTz( const QString &newCountry, const QString &newCity ); + +protected: + virtual void viewportMouseMoveEvent( QMouseEvent *event ); + virtual void viewportMousePressEvent( QMouseEvent *event ); + virtual void viewportMouseReleaseEvent( QMouseEvent *event ); + virtual void keyPressEvent( QKeyEvent * ); + virtual void resizeEvent( QResizeEvent *); + virtual void drawContents( QPainter *p, int cx, int cy, int cw, int ch ); + +private: + ZoneField *findCityNear( ZoneField *city, int key ); + void showCity( ZoneField *city ); + void drawCities( QPainter *p ); // put all the cities on the map (ugly) + void drawCity( QPainter *p, const ZoneField *pCity ); // draw the given city on the map + void readZones( void ); // Read in the zone information from the file + void zoom( void ); // Zoom the map... + void makeMap( int width, int height ); + QPixmap* pixCurr; // image to be drawn on the screen + QLabel* lblCity; // the "tool-tip" that shows up when you pick a city... + QToolButton *cmdZoom; // our zoom option... + QTimer* tHide; // the timer to hide the "tool tip" + ZoneField *pLast; // the last known good city that was found... + ZoneField *pRepaint; // save the location to maximize the repaint... + QList zones; // a linked list to hold all this information + StylusNormalizer norm; + + //the True width and height of the map... + int wImg; + int hImg; + // the pixel points that correspond to (0, 0); + int ox; + int oy; + + // the drawable area of the map... + int drawableW; + int drawableH; + + bool bZoom; // a flag to indicate zoom is active + bool bIllum; // flag to indicat that illumination is active + bool ampm; + + ZoneField *cursor; +}; + +inline bool ZoneMap::zoneToWin( int zoneX, int zoneY, + int &winX, int &winY ) const +{ + winY = oy - ( ( hImg * zoneY ) / 648000 ); // 180 degrees in secs + winX = ox + ( ( wImg * zoneX ) / 1296000 ); // 360 degrees in secs + // whoa, some things aren't in the best spots.. + if ( winX > wImg ) { + winX = wImg - iCITYOFFSET; + } else if ( winX <= 0 ) { + winX = iCITYOFFSET; + } + + if ( winY >= hImg ) { + winY = hImg - iCITYOFFSET; + } else if ( winY <= 0 ) { + winY = iCITYOFFSET; + } + // perhaps in the future there will be some real error checking + // for now just return true... + return true; +} + +inline bool ZoneMap::winToZone( int winX, int winY, + int &zoneX, int &zoneY ) const +{ + zoneY = ( 648000 * ( oy - winY ) ) / hImg; + zoneX = ( 1296000 * ( winX - ox ) ) / wImg; + // perhaps in the future there will be some real error checking + // for now just return true... + return true; +} + +#endif diff --git a/core/settings/light-and-power/.cvsignore b/core/settings/light-and-power/.cvsignore new file mode 100644 index 0000000..e6ba7a1 --- a/dev/null +++ b/core/settings/light-and-power/.cvsignore @@ -0,0 +1,4 @@ +moc_* +Makefile +lightsettingsbase.h +lightsettingsbase.cpp diff --git a/core/settings/light-and-power/Makefile.in b/core/settings/light-and-power/Makefile.in new file mode 100644 index 0000000..8236ed0 --- a/dev/null +++ b/core/settings/light-and-power/Makefile.in @@ -0,0 +1,135 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../../bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = light-and-power +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = settings.h +SOURCES = light.cpp \ + main.cpp +OBJECTS = light.o \ + main.o \ + lightsettingsbase.o +INTERFACES = lightsettingsbase.ui +UICDECLS = lightsettingsbase.h +UICIMPLS = lightsettingsbase.cpp +SRCMOC = moc_settings.cpp \ + moc_lightsettingsbase.cpp +OBJMOC = moc_settings.o \ + moc_lightsettingsbase.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake light-and-power.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +light.o: light.cpp \ + settings.h \ + lightsettingsbase.h + +main.o: main.cpp \ + settings.h \ + lightsettingsbase.h + +lightsettingsbase.h: lightsettingsbase.ui + $(UIC) lightsettingsbase.ui -o $(INTERFACE_DECL_PATH)/lightsettingsbase.h + +lightsettingsbase.cpp: lightsettingsbase.ui + $(UIC) lightsettingsbase.ui -i lightsettingsbase.h -o lightsettingsbase.cpp + +lightsettingsbase.o: lightsettingsbase.cpp \ + lightsettingsbase.h \ + lightsettingsbase.ui + +moc_settings.o: moc_settings.cpp \ + settings.h \ + lightsettingsbase.h + +moc_lightsettingsbase.o: moc_lightsettingsbase.cpp \ + lightsettingsbase.h + +moc_settings.cpp: settings.h + $(MOC) settings.h -o moc_settings.cpp + +moc_lightsettingsbase.cpp: lightsettingsbase.h + $(MOC) lightsettingsbase.h -o moc_lightsettingsbase.cpp + + diff --git a/core/settings/light-and-power/light-and-power.pro b/core/settings/light-and-power/light-and-power.pro new file mode 100644 index 0000000..87bb111 --- a/dev/null +++ b/core/settings/light-and-power/light-and-power.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +CONFIG += qt warn_on release +DESTDIR = ../../bin +HEADERS = settings.h +SOURCES = light.cpp main.cpp +INTERFACES = lightsettingsbase.ui +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += ../$(QPEDIR)/include +LIBS += -lqpe +TARGET = light-and-power + +TRANSLATIONS = ../../i18n/de/light-and-power.ts diff --git a/core/settings/light-and-power/light-off.xpm b/core/settings/light-and-power/light-off.xpm new file mode 100644 index 0000000..26624c7 --- a/dev/null +++ b/core/settings/light-and-power/light-off.xpm @@ -0,0 +1,23 @@ +/* XPM */ +static char * light_off_xpm[] = { +"16 16 4 1", +" c None", +". c #000000000000", +"X c #6B6B6C6C6C6C", +"o c #FFFF6C6C0000", +" ", +" ", +" ... ", +" . . ", +" . X. ", +" . X. ", +" . XXX. ", +" . X XX. ", +" . XX. ", +" . XXX. ", +" . X. ", +" . X.. ", +" .ooo.. ", +" .ooo.. ", +" .o.. ", +" .. "}; diff --git a/core/settings/light-and-power/light-on.xpm b/core/settings/light-and-power/light-on.xpm new file mode 100644 index 0000000..3f8e174 --- a/dev/null +++ b/core/settings/light-and-power/light-on.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char * light_on_xpm[] = { +"16 16 5 1", +" c None", +". c #FFFFFFFF0000", +"X c #000000000000", +"o c #FFFFFFFFFFFF", +"O c #FFFF6C6C0000", +" . . ", +" . . . ", +" . XXX . ", +" XoooX . ", +" Xoooo.X ", +" .. Xoooooo.X ", +" Xoooo...X ..", +" Xooo.o..X ", +" .. Xooo..X ", +" Xoo...X ", +" . Xoo.X . ", +" . Xoo.XX . ", +" XOOOXX ", +" XOOOXX ", +" XOXX ", +" XX "}; diff --git a/core/settings/light-and-power/light.cpp b/core/settings/light-and-power/light.cpp new file mode 100644 index 0000000..24e1fab --- a/dev/null +++ b/core/settings/light-and-power/light.cpp @@ -0,0 +1,133 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "settings.h" + +#include +#include +#include +#include +#include +#if defined(Q_WS_QWS) && !defined(QT_NO_COP) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if QT_VERSION >= 300 +#include +#endif + +extern int qpe_sysBrightnessSteps(); + +LightSettings::LightSettings( QWidget* parent, const char* name, WFlags fl ) + : LightSettingsBase( parent, name, TRUE, fl ) +{ + // Not supported + auto_brightness->hide(); + + Config config( "qpe" ); + + config.setGroup( "Screensaver" ); + + int interval; + interval = config.readNumEntry( "Interval_Dim", 30 ); + interval_dim->setValue( interval ); + interval = config.readNumEntry( "Interval_LightOff", 20 ); + interval_lightoff->setValue( interval ); + interval = config.readNumEntry( "Interval", 60 ); + if ( interval > 3600 ) interval /= 1000; // compatibility (was millisecs) + interval_suspend->setValue( interval ); + + screensaver_dim->setChecked( config.readNumEntry("Dim",1) != 0 ); + screensaver_lightoff->setChecked( config.readNumEntry("LightOff",1) != 0 ); + int maxbright = qpe_sysBrightnessSteps(); + initbright = config.readNumEntry("Brightness",255); + brightness->setMaxValue( maxbright ); + brightness->setTickInterval( QMAX(1,maxbright/16) ); + brightness->setLineStep( QMAX(1,maxbright/16) ); + brightness->setPageStep( QMAX(1,maxbright/16) ); + brightness->setValue( (maxbright*255 - initbright*maxbright)/255 ); + + connect(brightness, SIGNAL(valueChanged(int)), this, SLOT(applyBrightness())); +} + +LightSettings::~LightSettings() +{ +} + +static void set_fl(int bright) +{ + QCopEnvelope e("QPE/System", "setBacklight(int)" ); + e << bright; +} + +void LightSettings::reject() +{ + set_fl(initbright); + + QDialog::reject(); +} + +void LightSettings::accept() +{ + if ( qApp->focusWidget() ) + qApp->focusWidget()->clearFocus(); + + applyBrightness(); + + int i_dim = (screensaver_dim->isChecked() ? interval_dim->value() : 0); + int i_lightoff = (screensaver_lightoff->isChecked() ? interval_lightoff->value() : 0); + int i_suspend = interval_suspend->value(); + QCopEnvelope e("QPE/System", "setScreenSaverIntervals(int,int,int)" ); + e << i_dim << i_lightoff << i_suspend; + + Config config( "qpe" ); + config.setGroup( "Screensaver" ); + config.writeEntry( "Dim", (int)screensaver_dim->isChecked() ); + config.writeEntry( "LightOff", (int)screensaver_lightoff->isChecked() ); + config.writeEntry( "Interval_Dim", interval_dim->value() ); + config.writeEntry( "Interval_LightOff", interval_lightoff->value() ); + config.writeEntry( "Interval", interval_suspend->value() ); + config.writeEntry( "Brightness", + (brightness->maxValue()-brightness->value())*255/brightness->maxValue() ); + config.write(); + + QDialog::accept(); +} + +void LightSettings::applyBrightness() +{ + int bright = (brightness->maxValue()-brightness->value())*255 + / brightness->maxValue(); + set_fl(bright); +} + + diff --git a/core/settings/light-and-power/lightsettingsbase.ui b/core/settings/light-and-power/lightsettingsbase.ui new file mode 100644 index 0000000..47775f7 --- a/dev/null +++ b/core/settings/light-and-power/lightsettingsbase.ui @@ -0,0 +1,471 @@ + +LightSettingsBase + + QDialog + + name + LightSettingsBase + + + geometry + + 0 + 0 + 256 + 316 + + + + caption + Light Settings + + + layoutMargin + + + + margin + 7 + + + spacing + 6 + + + QCheckBox + + name + auto_brightness + + + text + Adjust to environment + + + whatsThis + By sensing the ambient light where you are using your device, the screen light can be adjusted automatically. The brightness setting still affects the average brightness. + + + + QGroupBox + + name + GroupBox3 + + + title + Power saving + + + layoutMargin + + + layoutSpacing + + + + margin + 6 + + + spacing + 3 + + + QSpinBox + + name + interval_lightoff + + + suffix + seconds + + + buttonSymbols + PlusMinus + + + maxValue + 3600 + + + minValue + 10 + + + lineStep + 15 + + + + QSpinBox + + name + interval_suspend + + + suffix + seconds + + + buttonSymbols + PlusMinus + + + maxValue + 3600 + + + minValue + 10 + + + lineStep + 15 + + + + QCheckBox + + name + screensaver_lightoff + + + sizePolicy + + 1 + 0 + + + + text + Light off after + + + checked + true + + + + QCheckBox + + name + screensaver_dim + + + sizePolicy + + 1 + 0 + + + + text + Dim light after + + + checked + true + + + + QSpinBox + + name + interval_dim + + + suffix + seconds + + + buttonSymbols + PlusMinus + + + maxValue + 3600 + + + minValue + 10 + + + lineStep + 15 + + + + QLabel + + name + TextLabel1_2 + + + text + Suspend after + + + + + + QLayoutWidget + + name + Layout18 + + + layoutMargin + + + + margin + 0 + + + spacing + 6 + + + QSlider + + name + brightness + + + maxValue + 255 + + + lineStep + 16 + + + pageStep + 16 + + + orientation + Vertical + + + tickmarks + Right + + + tickInterval + 32 + + + + QLayoutWidget + + name + Layout16 + + + layoutSpacing + + + + margin + 0 + + + spacing + 0 + + + QLayoutWidget + + name + Layout10 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + PixmapLabel1 + + + pixmap + image0 + + + scaledContents + false + + + + QLabel + + name + TextLabel1 + + + text + Bright + + + + + name + Spacer3 + + + orientation + Horizontal + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + QLabel + + name + TextLabel3 + + + sizePolicy + + 5 + 7 + + + + text + <blockquote>The brighter the screen light, the more battery power is used.</blockquote> + + + + QLayoutWidget + + name + Layout9 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + PixmapLabel2 + + + pixmap + image1 + + + scaledContents + false + + + + QLabel + + name + TextLabel2 + + + text + Off + + + alignment + AlignVCenter|AlignLeft + + + vAlign + + + + + name + Spacer2 + + + orientation + Horizontal + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + + + + + + + + image0 + 789c6d8ec10ac2300c86ef7b8ad0ff36a4730777111f41f1288887b4b3e8610a3a0f22bebb6dd3d54d0ca5cdffe54f9aaaa4dd764d6555dc7beecf96ec896f54b68fae7bee0fab57a1ea86fc5950ad6685d2646973bd1c43ce3ec73c46903648e79a5624443a27d20cd2b9382704747e124382f11a7c5e30b364b957b331866331b3800c38f70282121c7c628367c098c1e0eb03121ccd4b46fcb0f80b26bb4833987f76b6d6f274de5fe6a1a031d30969f55e161fe4715f7b + + + image1 + 789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523234530022130543251d2e253d856405bffcbc54105b19c856360003103711c4354b344b314b04719340dcb434b31488ac1e1a2020a6acac8c2ea60cc54862606ea232b218541b5810452c3111432c510f550c22886a1e482c115d0c2c88e6168818babaa4a42462c48082cae8e68102011a06b5d65c0041d3518e + + + + + screensaver_dim + toggled(bool) + interval_dim + setEnabled(bool) + + + screensaver_lightoff + toggled(bool) + interval_lightoff + setEnabled(bool) + + + + auto_brightness + screensaver_dim + interval_dim + screensaver_lightoff + interval_lightoff + interval_suspend + brightness + + diff --git a/core/settings/light-and-power/main.cpp b/core/settings/light-and-power/main.cpp new file mode 100644 index 0000000..051fdec --- a/dev/null +++ b/core/settings/light-and-power/main.cpp @@ -0,0 +1,38 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "settings.h" + +#include +#include +#include + + +int main(int argc, char** argv) +{ + QPEApplication a(argc,argv); + + LightSettings dlg; + + a.showMainWidget(&dlg); + + return a.exec(); +} + diff --git a/core/settings/light-and-power/qpe-light-and-power.control b/core/settings/light-and-power/qpe-light-and-power.control new file mode 100644 index 0000000..0ed9d84 --- a/dev/null +++ b/core/settings/light-and-power/qpe-light-and-power.control @@ -0,0 +1,9 @@ +Files: bin/light-and-power apps/Settings/Light.desktop +Priority: optional +Section: qpe/settings +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: Light and Power settings dialog + For the Qtopia environment. diff --git a/core/settings/light-and-power/settings.h b/core/settings/light-and-power/settings.h new file mode 100644 index 0000000..cec08e3 --- a/dev/null +++ b/core/settings/light-and-power/settings.h @@ -0,0 +1,50 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef SETTINGS_H +#define SETTINGS_H + + +#include +#include +#include "lightsettingsbase.h" + + +class LightSettings : public LightSettingsBase +{ + Q_OBJECT + +public: + LightSettings( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~LightSettings(); + +protected: + void accept(); + void reject(); + +private slots: + void applyBrightness(); + +private: + int initbright; +}; + + +#endif // SETTINGS_H + diff --git a/core/settings/security/.cvsignore b/core/settings/security/.cvsignore new file mode 100644 index 0000000..11eef0d --- a/dev/null +++ b/core/settings/security/.cvsignore @@ -0,0 +1,5 @@ +Makefile +moc_* +*.moc +securitybase.cpp +securitybase.h diff --git a/core/settings/security/Makefile.in b/core/settings/security/Makefile.in new file mode 100644 index 0000000..803edc5 --- a/dev/null +++ b/core/settings/security/Makefile.in @@ -0,0 +1,135 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../../bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = security +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = security.h +SOURCES = security.cpp \ + main.cpp +OBJECTS = security.o \ + main.o \ + securitybase.o +INTERFACES = securitybase.ui +UICDECLS = securitybase.h +UICIMPLS = securitybase.cpp +SRCMOC = moc_security.cpp \ + moc_securitybase.cpp +OBJMOC = moc_security.o \ + moc_securitybase.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake security.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +security.o: security.cpp \ + security.h \ + securitybase.h + +main.o: main.cpp \ + security.h \ + securitybase.h + +securitybase.h: securitybase.ui + $(UIC) securitybase.ui -o $(INTERFACE_DECL_PATH)/securitybase.h + +securitybase.cpp: securitybase.ui + $(UIC) securitybase.ui -i securitybase.h -o securitybase.cpp + +securitybase.o: securitybase.cpp \ + securitybase.h \ + securitybase.ui + +moc_security.o: moc_security.cpp \ + security.h \ + securitybase.h + +moc_securitybase.o: moc_securitybase.cpp \ + securitybase.h + +moc_security.cpp: security.h + $(MOC) security.h -o moc_security.cpp + +moc_securitybase.cpp: securitybase.h + $(MOC) securitybase.h -o moc_securitybase.cpp + + diff --git a/core/settings/security/main.cpp b/core/settings/security/main.cpp new file mode 100644 index 0000000..c15bb31 --- a/dev/null +++ b/core/settings/security/main.cpp @@ -0,0 +1,38 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include +#include +#include + +#include "security.h" + + +int main(int argc, char** argv) +{ + QPEApplication a(argc,argv); + + Security dlg; + + a.showMainWidget(&dlg); + + return a.exec(); +} + diff --git a/core/settings/security/qpe-security.control b/core/settings/security/qpe-security.control new file mode 100644 index 0000000..78a5a86 --- a/dev/null +++ b/core/settings/security/qpe-security.control @@ -0,0 +1,9 @@ +Files: bin/security apps/Settings/Security.desktop +Priority: optional +Section: qpe/settings +Maintainer: Warwick Allison +Architecture: arm +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: Security settings dialog + For the Qtopia environment. diff --git a/core/settings/security/security.cpp b/core/settings/security/security.cpp new file mode 100644 index 0000000..f4116b0 --- a/dev/null +++ b/core/settings/security/security.cpp @@ -0,0 +1,234 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "security.h" + +#include +#include +#include + +#include +#include +#include +#include + +Security::Security( QWidget* parent, const char* name, WFlags fl ) + : SecurityBase( parent, name, TRUE, fl ) +{ + valid=FALSE; + Config cfg("Security"); + cfg.setGroup("Passcode"); + passcode = cfg.readEntry("passcode"); + passcode_poweron->setChecked(cfg.readBoolEntry("passcode_poweron",FALSE)); + cfg.setGroup("Sync"); + int auth_peer = cfg.readNumEntry("auth_peer",0xc0a80100); + int auth_peer_bits = cfg.readNumEntry("auth_peer_bits",24); + selectNet(auth_peer,auth_peer_bits); + connect(syncnet, SIGNAL(textChanged(const QString&)), + this, SLOT(setSyncNet(const QString&))); + + /* + cfg.setGroup("Remote"); + if ( telnetAvailable() ) + telnet->setChecked(cfg.readEntry("allow_telnet")); + else + telnet->hide(); + + if ( sshAvailable() ) + ssh->setChecked(cfg.readEntry("allow_ssh")); + else + ssh->hide(); + */ + + connect(changepasscode,SIGNAL(clicked()), this, SLOT(changePassCode())); + connect(clearpasscode,SIGNAL(clicked()), this, SLOT(clearPassCode())); + updateGUI(); + + dl = new QPEDialogListener(this); +} + +Security::~Security() +{ +} + + +void Security::updateGUI() +{ + bool empty = passcode.isEmpty(); + + changepasscode->setText( empty ? tr("Set passcode" ) + : tr("Change passcode" ) ); + passcode_poweron->setEnabled( !empty ); + clearpasscode->setEnabled( !empty ); +} + + +void Security::show() +{ + valid=FALSE; + setEnabled(FALSE); + SecurityBase::show(); + if ( passcode.isEmpty() ) { + // could insist... + //changePassCode(); + //if ( passcode.isEmpty() ) + //reject(); + } else { + QString pc = enterPassCode(tr("Enter passcode")); + if ( pc != passcode ) { + QMessageBox::critical(this, tr("Passcode incorrect"), + tr("The passcode entered is incorrect.\nAccess denied")); + reject(); + return; + } + } + setEnabled(TRUE); + valid=TRUE; +} + +void Security::accept() +{ + applySecurity(); + QDialog::accept(); +} + +void Security::done(int r) +{ + QDialog::done(r); + close(); +} + +void Security::selectNet(int auth_peer,int auth_peer_bits) +{ + QString sn; + if ( auth_peer_bits == 0 && auth_peer == 0 ) { + sn = tr("Any"); + } else if ( auth_peer_bits == 32 && auth_peer == 0 ) { + sn = tr("None"); + } else { + sn = + QString::number((auth_peer>>24)&0xff) + "." + + QString::number((auth_peer>>16)&0xff) + "." + + QString::number((auth_peer>>8)&0xff) + "." + + QString::number((auth_peer>>0)&0xff) + "/" + + QString::number(auth_peer_bits); + } + for (int i=0; icount(); i++) { + if ( syncnet->text(i).left(sn.length()) == sn ) { + syncnet->setCurrentItem(i); + return; + } + } + qDebug("No match for \"%s\"",sn.latin1()); +} + +void Security::parseNet(const QString& sn,int& auth_peer,int& auth_peer_bits) +{ + auth_peer=0; + if ( sn == tr("Any") ) { + auth_peer = 0; + auth_peer_bits = 0; + } else if ( sn == tr("None") ) { + auth_peer = 0; + auth_peer_bits = 32; + } else { + int x=0; + for (int i=0; i<4; i++) { + int nx = sn.find(QChar(i==3 ? '/' : '.'),x); + auth_peer = (auth_peer<<8)|sn.mid(x,nx-x).toInt(); + x = nx+1; + } + uint n = (uint)sn.find(' ',x)-x; + auth_peer_bits = sn.mid(x,n).toInt(); + } +} + +void Security::setSyncNet(const QString& sn) +{ + int auth_peer,auth_peer_bits; + parseNet(sn,auth_peer,auth_peer_bits); + selectNet(auth_peer,auth_peer_bits); +} + +void Security::applySecurity() +{ + if ( valid ) { + Config cfg("Security"); + cfg.setGroup("Passcode"); + cfg.writeEntry("passcode",passcode); + cfg.writeEntry("passcode_poweron",passcode_poweron->isChecked()); + cfg.setGroup("Sync"); + int auth_peer=0; + int auth_peer_bits; + QString sn = syncnet->currentText(); + parseNet(sn,auth_peer,auth_peer_bits); + cfg.writeEntry("auth_peer",auth_peer); + cfg.writeEntry("auth_peer_bits",auth_peer_bits); + /* + cfg.setGroup("Remote"); + if ( telnetAvailable() ) + cfg.writeEntry("allow_telnet",telnet->isChecked()); + if ( sshAvailable() ) + cfg.writeEntry("allow_ssh",ssh->isChecked()); + // ### write ssh/telnet sys config files + */ + } +} + +void Security::changePassCode() +{ + QString new1; + QString new2; + + do { + new1 = enterPassCode("Enter new passcode"); + if ( new1.isNull() ) + return; + new2 = enterPassCode("Re-enter new passcode"); + if ( new2.isNull() ) + return; + } while (new1 != new2); + + passcode = new1; + updateGUI(); +} + +void Security::clearPassCode() +{ + passcode = QString::null; + updateGUI(); +} + + +QString Security::enterPassCode(const QString& prompt) +{ + return Password::getPassword(prompt); +} + +bool Security::telnetAvailable() const +{ + // ### not implemented + return FALSE; +} + +bool Security::sshAvailable() const +{ + // ### not implemented + return FALSE; +} diff --git a/core/settings/security/security.h b/core/settings/security/security.h new file mode 100644 index 0000000..efc83a2 --- a/dev/null +++ b/core/settings/security/security.h @@ -0,0 +1,64 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef SECURITY_H +#define SECURITY_H + +#include "securitybase.h" + +class QPEDialogListener; + +class Security : public SecurityBase +{ + Q_OBJECT + +public: + Security( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~Security(); + + void show(); + +protected: + void accept(); + void applySecurity(); + void done(int); + +private slots: + void changePassCode(); + void clearPassCode(); + void setSyncNet(const QString&); + +private: + bool telnetAvailable() const; + bool sshAvailable() const; + void updateGUI(); + + static void parseNet(const QString& sn,int& auth_peer,int& auth_peer_bits); + void selectNet(int auth_peer,int auth_peer_bits); + + QString enterPassCode(const QString&); + QString passcode; + bool valid; + + QPEDialogListener *dl; +}; + + +#endif // SECURITY_H + diff --git a/core/settings/security/security.pro b/core/settings/security/security.pro new file mode 100644 index 0000000..282127e --- a/dev/null +++ b/core/settings/security/security.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +CONFIG += qt warn_on release +DESTDIR = ../../bin +HEADERS = security.h +SOURCES = security.cpp main.cpp +INTERFACES = securitybase.ui +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += ../$(QPEDIR)/include +LIBS += -lqpe +TARGET = security + +TRANSLATIONS = ../../i18n/de/security.ts diff --git a/core/settings/security/securitybase.ui b/core/settings/security/securitybase.ui new file mode 100644 index 0000000..2f3189d --- a/dev/null +++ b/core/settings/security/securitybase.ui @@ -0,0 +1,200 @@ + +SecurityBase + + QDialog + + name + SecurityBase + + + geometry + + 0 + 0 + 281 + 328 + + + + caption + Security Settings + + + layoutMargin + + + + margin + 11 + + + spacing + 6 + + + QLayoutWidget + + name + Layout1 + + + layoutSpacing + + + + margin + 0 + + + spacing + -1 + + + QPushButton + + name + changepasscode + + + text + Change passcode + + + + QPushButton + + name + clearpasscode + + + text + Clear passcode + + + + + + QCheckBox + + name + passcode_poweron + + + text + Require pass code at power-on + + + + QTabWidget + + name + TabWidget2 + + + QWidget + + name + tab + + + title + Sync + + + + margin + 11 + + + spacing + 6 + + + QLabel + + name + TextLabel1_2 + + + text + Accept sync from network: + + + + QComboBox + + + text + 192.168.1.0/24 (default) + + + + + text + 192.168.0.0/16 + + + + + text + 172.16.0.0/12 + + + + + text + 10.0.0.0/8 + + + + + text + Any + + + + + text + None + + + + name + syncnet + + + editable + true + + + + + + + QLabel + + name + TextLabel1 + + + sizePolicy + + 5 + 7 + + + + text + <P>Pass code protection provides a minimal level of protection from casual access to this device. + + + alignment + AlignTop|AlignLeft + + + vAlign + + + + + -- cgit v0.9.0.2