Chris@1262: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@1262: Chris@1262: /* Chris@1262: Sonic Visualiser Chris@1262: An audio file viewer and annotation editor. Chris@1262: Centre for Digital Music, Queen Mary, University of London. Chris@1262: Chris@1262: This program is free software; you can redistribute it and/or Chris@1262: modify it under the terms of the GNU General Public License as Chris@1262: published by the Free Software Foundation; either version 2 of the Chris@1262: License, or (at your option) any later version. See the file Chris@1262: COPYING included with this distribution for more information. Chris@1262: */ Chris@1262: Chris@1262: #ifndef TEST_VAMP_REALTIME_H Chris@1262: Chris@1262: #include Chris@1262: #include Chris@1262: #include Chris@1262: Chris@1262: #include Chris@1262: Chris@1262: #include Chris@1262: Chris@1262: using namespace std; Chris@1262: Chris@1262: #define ONE_MILLION 1000000 Chris@1262: #define ONE_BILLION 1000000000 Chris@1262: Chris@1262: class TestVampRealTime : public QObject Chris@1262: { Chris@1262: Q_OBJECT Chris@1262: Chris@1262: void compareTexts(string s, const char *e) { Chris@1262: QCOMPARE(QString(s.c_str()), QString(e)); Chris@1262: } Chris@1262: Chris@1262: typedef Vamp::RealTime RealTime; Chris@1262: typedef long frame_type; Chris@1262: Chris@1262: private slots: Chris@1262: Chris@1262: void zero() Chris@1262: { Chris@1262: QCOMPARE(RealTime(0, 0), RealTime::zeroTime); Chris@1262: QCOMPARE(RealTime(0, 0).sec, 0); Chris@1262: QCOMPARE(RealTime(0, 0).nsec, 0); Chris@1262: QCOMPARE(RealTime(0, 0).msec(), 0); Chris@1262: QCOMPARE(RealTime(0, 0).usec(), 0); Chris@1262: } Chris@1262: Chris@1262: void ctor() Chris@1262: { Chris@1262: QCOMPARE(RealTime(0, 0), RealTime(0, 0)); Chris@1262: Chris@1262: // wraparounds Chris@1262: QCOMPARE(RealTime(0, ONE_BILLION/2), RealTime(1, -ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime(0, -ONE_BILLION/2), RealTime(-1, ONE_BILLION/2)); Chris@1262: Chris@1262: QCOMPARE(RealTime(1, ONE_BILLION), RealTime(2, 0)); Chris@1262: QCOMPARE(RealTime(1, -ONE_BILLION), RealTime(0, 0)); Chris@1262: QCOMPARE(RealTime(-1, ONE_BILLION), RealTime(0, 0)); Chris@1262: QCOMPARE(RealTime(-1, -ONE_BILLION), RealTime(-2, 0)); Chris@1262: Chris@1262: QCOMPARE(RealTime(2, -ONE_BILLION*2), RealTime(0, 0)); Chris@1262: QCOMPARE(RealTime(2, -ONE_BILLION/2), RealTime(1, ONE_BILLION/2)); Chris@1262: Chris@1262: QCOMPARE(RealTime(-2, ONE_BILLION*2), RealTime(0, 0)); Chris@1262: QCOMPARE(RealTime(-2, ONE_BILLION/2), RealTime(-1, -ONE_BILLION/2)); Chris@1262: Chris@1262: QCOMPARE(RealTime(0, 1).sec, 0); Chris@1262: QCOMPARE(RealTime(0, 1).nsec, 1); Chris@1262: QCOMPARE(RealTime(0, -1).sec, 0); Chris@1262: QCOMPARE(RealTime(0, -1).nsec, -1); Chris@1262: QCOMPARE(RealTime(1, -1).sec, 0); Chris@1262: QCOMPARE(RealTime(1, -1).nsec, ONE_BILLION-1); Chris@1262: QCOMPARE(RealTime(-1, 1).sec, 0); Chris@1262: QCOMPARE(RealTime(-1, 1).nsec, -ONE_BILLION+1); Chris@1262: QCOMPARE(RealTime(-1, -1).sec, -1); Chris@1262: QCOMPARE(RealTime(-1, -1).nsec, -1); Chris@1262: Chris@1262: QCOMPARE(RealTime(2, -ONE_BILLION*2).sec, 0); Chris@1262: QCOMPARE(RealTime(2, -ONE_BILLION*2).nsec, 0); Chris@1262: QCOMPARE(RealTime(2, -ONE_BILLION/2).sec, 1); Chris@1262: QCOMPARE(RealTime(2, -ONE_BILLION/2).nsec, ONE_BILLION/2); Chris@1262: Chris@1262: QCOMPARE(RealTime(-2, ONE_BILLION*2).sec, 0); Chris@1262: QCOMPARE(RealTime(-2, ONE_BILLION*2).nsec, 0); Chris@1262: QCOMPARE(RealTime(-2, ONE_BILLION/2).sec, -1); Chris@1262: QCOMPARE(RealTime(-2, ONE_BILLION/2).nsec, -ONE_BILLION/2); Chris@1262: } Chris@1262: Chris@1262: void fromSeconds() Chris@1262: { Chris@1262: QCOMPARE(RealTime::fromSeconds(0), RealTime(0, 0)); Chris@1262: Chris@1262: QCOMPARE(RealTime::fromSeconds(0.5).sec, 0); Chris@1262: QCOMPARE(RealTime::fromSeconds(0.5).nsec, ONE_BILLION/2); Chris@1262: QCOMPARE(RealTime::fromSeconds(0.5).usec(), ONE_MILLION/2); Chris@1262: QCOMPARE(RealTime::fromSeconds(0.5).msec(), 500); Chris@1262: Chris@1262: QCOMPARE(RealTime::fromSeconds(0.5), RealTime(0, ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime::fromSeconds(1), RealTime(1, 0)); Chris@1262: QCOMPARE(RealTime::fromSeconds(1.5), RealTime(1, ONE_BILLION/2)); Chris@1262: Chris@1262: QCOMPARE(RealTime::fromSeconds(-0.5).sec, 0); Chris@1262: QCOMPARE(RealTime::fromSeconds(-0.5).nsec, -ONE_BILLION/2); Chris@1262: QCOMPARE(RealTime::fromSeconds(-0.5).usec(), -ONE_MILLION/2); Chris@1262: QCOMPARE(RealTime::fromSeconds(-0.5).msec(), -500); Chris@1262: Chris@1262: QCOMPARE(RealTime::fromSeconds(-1.5).sec, -1); Chris@1262: QCOMPARE(RealTime::fromSeconds(-1.5).nsec, -ONE_BILLION/2); Chris@1262: QCOMPARE(RealTime::fromSeconds(-1.5).usec(), -ONE_MILLION/2); Chris@1262: QCOMPARE(RealTime::fromSeconds(-1.5).msec(), -500); Chris@1262: Chris@1262: QCOMPARE(RealTime::fromSeconds(-0.5), RealTime(0, -ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime::fromSeconds(-1), RealTime(-1, 0)); Chris@1262: QCOMPARE(RealTime::fromSeconds(-1.5), RealTime(-1, -ONE_BILLION/2)); Chris@1262: } Chris@1262: Chris@1262: void fromMilliseconds() Chris@1262: { Chris@1262: QCOMPARE(RealTime::fromMilliseconds(0), RealTime(0, 0)); Chris@1262: QCOMPARE(RealTime::fromMilliseconds(500), RealTime(0, ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime::fromMilliseconds(1000), RealTime(1, 0)); Chris@1262: QCOMPARE(RealTime::fromMilliseconds(1500), RealTime(1, ONE_BILLION/2)); Chris@1262: Chris@1262: QCOMPARE(RealTime::fromMilliseconds(-0), RealTime(0, 0)); Chris@1262: QCOMPARE(RealTime::fromMilliseconds(-500), RealTime(0, -ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime::fromMilliseconds(-1000), RealTime(-1, 0)); Chris@1262: QCOMPARE(RealTime::fromMilliseconds(-1500), RealTime(-1, -ONE_BILLION/2)); Chris@1262: } Chris@1262: Chris@1262: void fromTimeval() Chris@1262: { Chris@1262: struct timeval tv; Chris@1262: Chris@1262: tv.tv_sec = 0; tv.tv_usec = 0; Chris@1262: QCOMPARE(RealTime::fromTimeval(tv), RealTime(0, 0)); Chris@1262: tv.tv_sec = 0; tv.tv_usec = ONE_MILLION/2; Chris@1262: QCOMPARE(RealTime::fromTimeval(tv), RealTime(0, ONE_BILLION/2)); Chris@1262: tv.tv_sec = 1; tv.tv_usec = 0; Chris@1262: QCOMPARE(RealTime::fromTimeval(tv), RealTime(1, 0)); Chris@1262: tv.tv_sec = 1; tv.tv_usec = ONE_MILLION/2; Chris@1262: QCOMPARE(RealTime::fromTimeval(tv), RealTime(1, ONE_BILLION/2)); Chris@1262: Chris@1262: tv.tv_sec = 0; tv.tv_usec = -ONE_MILLION/2; Chris@1262: QCOMPARE(RealTime::fromTimeval(tv), RealTime(0, -ONE_BILLION/2)); Chris@1262: tv.tv_sec = -1; tv.tv_usec = 0; Chris@1262: QCOMPARE(RealTime::fromTimeval(tv), RealTime(-1, 0)); Chris@1262: tv.tv_sec = -1; tv.tv_usec = -ONE_MILLION/2; Chris@1262: QCOMPARE(RealTime::fromTimeval(tv), RealTime(-1, -ONE_BILLION/2)); Chris@1262: } Chris@1262: Chris@1262: void assign() Chris@1262: { Chris@1262: RealTime r; Chris@1262: r = RealTime(0, 0); Chris@1262: QCOMPARE(r, RealTime::zeroTime); Chris@1262: r = RealTime(0, ONE_BILLION/2); Chris@1262: QCOMPARE(r.sec, 0); Chris@1262: QCOMPARE(r.nsec, ONE_BILLION/2); Chris@1262: r = RealTime(-1, -ONE_BILLION/2); Chris@1262: QCOMPARE(r.sec, -1); Chris@1262: QCOMPARE(r.nsec, -ONE_BILLION/2); Chris@1262: } Chris@1262: Chris@1262: void plus() Chris@1262: { Chris@1262: QCOMPARE(RealTime(0, 0) + RealTime(0, 0), RealTime(0, 0)); Chris@1262: Chris@1262: QCOMPARE(RealTime(0, 0) + RealTime(0, ONE_BILLION/2), RealTime(0, ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime(0, ONE_BILLION/2) + RealTime(0, ONE_BILLION/2), RealTime(1, 0)); Chris@1262: QCOMPARE(RealTime(1, 0) + RealTime(0, ONE_BILLION/2), RealTime(1, ONE_BILLION/2)); Chris@1262: Chris@1262: QCOMPARE(RealTime(0, 0) + RealTime(0, -ONE_BILLION/2), RealTime(0, -ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime(0, -ONE_BILLION/2) + RealTime(0, -ONE_BILLION/2), RealTime(-1, 0)); Chris@1262: QCOMPARE(RealTime(-1, 0) + RealTime(0, -ONE_BILLION/2), RealTime(-1, -ONE_BILLION/2)); Chris@1262: Chris@1262: QCOMPARE(RealTime(1, 0) + RealTime(0, -ONE_BILLION/2), RealTime(0, ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime(1, 0) + RealTime(0, -ONE_BILLION/2) + RealTime(0, -ONE_BILLION/2), RealTime(0, 0)); Chris@1262: QCOMPARE(RealTime(1, 0) + RealTime(0, -ONE_BILLION/2) + RealTime(0, -ONE_BILLION/2) + RealTime(0, -ONE_BILLION/2), RealTime(0, -ONE_BILLION/2)); Chris@1262: Chris@1262: QCOMPARE(RealTime(0, ONE_BILLION/2) + RealTime(-1, 0), RealTime(0, -ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime(0, -ONE_BILLION/2) + RealTime(1, 0), RealTime(0, ONE_BILLION/2)); Chris@1262: } Chris@1262: Chris@1262: void minus() Chris@1262: { Chris@1262: QCOMPARE(RealTime(0, 0) - RealTime(0, 0), RealTime(0, 0)); Chris@1262: Chris@1262: QCOMPARE(RealTime(0, 0) - RealTime(0, ONE_BILLION/2), RealTime(0, -ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime(0, ONE_BILLION/2) - RealTime(0, ONE_BILLION/2), RealTime(0, 0)); Chris@1262: QCOMPARE(RealTime(1, 0) - RealTime(0, ONE_BILLION/2), RealTime(0, ONE_BILLION/2)); Chris@1262: Chris@1262: QCOMPARE(RealTime(0, 0) - RealTime(0, -ONE_BILLION/2), RealTime(0, ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime(0, -ONE_BILLION/2) - RealTime(0, -ONE_BILLION/2), RealTime(0, 0)); Chris@1262: QCOMPARE(RealTime(-1, 0) - RealTime(0, -ONE_BILLION/2), RealTime(0, -ONE_BILLION/2)); Chris@1262: Chris@1262: QCOMPARE(RealTime(1, 0) - RealTime(0, -ONE_BILLION/2), RealTime(1, ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime(1, 0) - RealTime(0, -ONE_BILLION/2) - RealTime(0, -ONE_BILLION/2), RealTime(2, 0)); Chris@1262: QCOMPARE(RealTime(1, 0) - RealTime(0, -ONE_BILLION/2) - RealTime(0, -ONE_BILLION/2) - RealTime(0, -ONE_BILLION/2), RealTime(2, ONE_BILLION/2)); Chris@1262: Chris@1262: QCOMPARE(RealTime(0, ONE_BILLION/2) - RealTime(-1, 0), RealTime(1, ONE_BILLION/2)); Chris@1262: QCOMPARE(RealTime(0, -ONE_BILLION/2) - RealTime(1, 0), RealTime(-1, -ONE_BILLION/2)); Chris@1262: } Chris@1262: Chris@1262: void negate() Chris@1262: { Chris@1262: QCOMPARE(-RealTime(0, 0), RealTime(0, 0)); Chris@1262: QCOMPARE(-RealTime(1, 0), RealTime(-1, 0)); Chris@1262: QCOMPARE(-RealTime(1, ONE_BILLION/2), RealTime(-1, -ONE_BILLION/2)); Chris@1262: QCOMPARE(-RealTime(-1, -ONE_BILLION/2), RealTime(1, ONE_BILLION/2)); Chris@1262: } Chris@1262: Chris@1262: void compare() Chris@1262: { Chris@1262: int sec, nsec; Chris@1262: for (sec = -2; sec <= 2; sec += 2) { Chris@1262: for (nsec = -1; nsec <= 1; nsec += 1) { Chris@1262: QCOMPARE(RealTime(sec, nsec) < RealTime(sec, nsec), false); Chris@1262: QCOMPARE(RealTime(sec, nsec) > RealTime(sec, nsec), false); Chris@1262: QCOMPARE(RealTime(sec, nsec) == RealTime(sec, nsec), true); Chris@1262: QCOMPARE(RealTime(sec, nsec) != RealTime(sec, nsec), false); Chris@1262: QCOMPARE(RealTime(sec, nsec) <= RealTime(sec, nsec), true); Chris@1262: QCOMPARE(RealTime(sec, nsec) >= RealTime(sec, nsec), true); Chris@1262: } Chris@1262: } Chris@1262: RealTime prev(-3, 0); Chris@1262: for (sec = -2; sec <= 2; sec += 2) { Chris@1262: for (nsec = -1; nsec <= 1; nsec += 1) { Chris@1262: Chris@1262: RealTime curr(sec, nsec); Chris@1262: Chris@1262: QCOMPARE(prev < curr, true); Chris@1262: QCOMPARE(prev > curr, false); Chris@1262: QCOMPARE(prev == curr, false); Chris@1262: QCOMPARE(prev != curr, true); Chris@1262: QCOMPARE(prev <= curr, true); Chris@1262: QCOMPARE(prev >= curr, false); Chris@1262: Chris@1262: QCOMPARE(curr < prev, false); Chris@1262: QCOMPARE(curr > prev, true); Chris@1262: QCOMPARE(curr == prev, false); Chris@1262: QCOMPARE(curr != prev, true); Chris@1262: QCOMPARE(curr <= prev, false); Chris@1262: QCOMPARE(curr >= prev, true); Chris@1262: Chris@1262: prev = curr; Chris@1262: } Chris@1262: } Chris@1262: } Chris@1262: Chris@1262: void frame() Chris@1262: { Chris@1262: int frames[] = { Chris@1262: 0, 1, 2047, 2048, 6656, Chris@1262: 32767, 32768, 44100, 44101, Chris@1262: 999999999, 2000000000 Chris@1262: }; Chris@1262: int n = sizeof(frames)/sizeof(frames[0]); Chris@1262: Chris@1262: int rates[] = { Chris@1262: 1, 2, 8000, 22050, Chris@1262: 44100, 44101, 192000, 2000000001 Chris@1262: }; Chris@1262: int m = sizeof(rates)/sizeof(rates[0]); Chris@1262: Chris@1262: vector> realTimes = { Chris@1262: { { 0, 0 }, { 1, 0 }, { 2047, 0 }, { 2048, 0 }, Chris@1262: { 6656, 0 }, { 32767, 0 }, { 32768, 0 }, { 44100, 0 }, Chris@1262: { 44101, 0 }, { 999999999, 0 }, { 2000000000, 0 } }, Chris@1262: { { 0, 0 }, { 0, 500000000 }, { 1023, 500000000 }, { 1024, 0 }, Chris@1262: { 3328, 0 }, { 16383, 500000000 }, { 16384, 0 }, { 22050, 0 }, Chris@1262: { 22050, 500000000 }, { 499999999, 500000000 }, { 1000000000, 0 } }, Chris@1262: { { 0, 0 }, { 0, 125000 }, { 0, 255875000 }, { 0, 256000000 }, Chris@1262: { 0, 832000000 }, { 4, 95875000 }, { 4, 96000000 }, { 5, 512500000 }, Chris@1262: { 5, 512625000 }, { 124999, 999875000 }, { 250000, 0 } }, Chris@1262: { { 0, 0 }, { 0, 45351 }, { 0, 92834467 }, { 0, 92879819 }, Chris@1262: { 0, 301859410 }, { 1, 486031746 }, { 1, 486077098 }, { 2, 0 }, Chris@1262: { 2, 45351 }, { 45351, 473877551 }, { 90702, 947845805 } }, Chris@1262: { { 0, 0 }, { 0, 22676 }, { 0, 46417234 }, { 0, 46439909 }, Chris@1262: { 0, 150929705 }, { 0, 743015873 }, { 0, 743038549 }, { 1, 0 }, Chris@1262: { 1, 22676 }, { 22675, 736938776 }, { 45351, 473922902 } }, Chris@1262: { { 0, 0 }, { 0, 22675 }, { 0, 46416181 }, { 0, 46438856 }, Chris@1262: { 0, 150926283 }, { 0, 742999025 }, { 0, 743021700 }, { 0, 999977325 }, Chris@1262: { 1, 0 }, { 22675, 222761389 }, { 45350, 445568128 } }, Chris@1262: { { 0, 0 }, { 0, 5208 }, { 0, 10661458 }, { 0, 10666667 }, Chris@1262: { 0, 34666667 }, { 0, 170661458 }, { 0, 170666667 }, { 0, 229687500 }, Chris@1262: { 0, 229692708 }, { 5208, 333328125 }, { 10416, 666666667 } }, Chris@1262: { { 0, 0 }, { 0, 0 }, { 0, 1023 }, { 0, 1024 }, Chris@1262: { 0, 3328 }, { 0, 16383 }, { 0, 16384 }, { 0, 22050 }, Chris@1262: { 0, 22050 }, { 0, 499999999 }, { 1, 0 } } Chris@1262: }; Chris@1262: Chris@1262: for (int i = 0; i < n; ++i) { Chris@1262: frame_type frame = frames[i]; Chris@1262: for (int j = 0; j < m; ++j) { Chris@1262: int rate = rates[j]; Chris@1262: Chris@1262: RealTime rt = RealTime::frame2RealTime(frame, rate); Chris@1262: QCOMPARE(rt.sec, realTimes[j][i].sec); Chris@1262: QCOMPARE(rt.nsec, realTimes[j][i].nsec); Chris@1262: Chris@1262: frame_type conv = RealTime::realTime2Frame(rt, rate); Chris@1262: Chris@1262: rt = RealTime::frame2RealTime(-frame, rate); Chris@1262: frame_type negconv = RealTime::realTime2Frame(rt, rate); Chris@1262: Chris@1262: if (rate > ONE_BILLION) { Chris@1263: // We don't have enough precision in RealTime Chris@1262: // for this absurd sample rate, so a round trip Chris@1262: // conversion may round Chris@1262: QVERIFY(abs(frame - conv) < 2); Chris@1262: QVERIFY(abs(-frame - negconv) < 2); Chris@1262: } else { Chris@1262: QCOMPARE(conv, frame); Chris@1262: QCOMPARE(negconv, -frame); Chris@1262: } Chris@1262: } Chris@1262: } Chris@1262: } Chris@1262: Chris@1262: // Vamp SDK version just has toText, which is like our own Chris@1262: // toMSText with true for its second arg Chris@1262: Chris@1262: void toText() Chris@1262: { Chris@1262: // we want to use QStrings, because then the Qt test library Chris@1262: // will print out any conflicts. The compareTexts function Chris@1262: // does this for us Chris@1262: Chris@1262: int halfSec = ONE_BILLION/2; // nsec Chris@1262: Chris@1262: RealTime rt = RealTime(0, 0); Chris@1262: compareTexts(rt.toText(false), "0"); Chris@1262: compareTexts(rt.toText(true), "0.000"); Chris@1262: Chris@1262: rt = RealTime(1, halfSec); Chris@1262: compareTexts(rt.toText(false), "1.5"); Chris@1262: compareTexts(rt.toText(true), "1.500"); Chris@1262: Chris@1262: rt = RealTime::fromSeconds(-1.5); Chris@1262: compareTexts(rt.toText(false), "-1.5"); Chris@1262: compareTexts(rt.toText(true), "-1.500"); Chris@1262: Chris@1262: rt = RealTime::fromSeconds(60); Chris@1262: compareTexts(rt.toText(false), "1:00"); Chris@1262: compareTexts(rt.toText(true), "1:00.000"); Chris@1262: Chris@1262: rt = RealTime::fromSeconds(61.05); Chris@1262: compareTexts(rt.toText(false), "1:01.05"); Chris@1262: compareTexts(rt.toText(true), "1:01.050"); Chris@1262: Chris@1262: rt = RealTime::fromSeconds(601.05); Chris@1262: compareTexts(rt.toText(false), "10:01.05"); Chris@1262: compareTexts(rt.toText(true), "10:01.050"); Chris@1262: Chris@1262: rt = RealTime::fromSeconds(3600); Chris@1262: compareTexts(rt.toText(false), "1:00:00"); Chris@1262: compareTexts(rt.toText(true), "1:00:00.000"); Chris@1262: Chris@1262: // For practical reasons our time display always rounds down Chris@1262: rt = RealTime(3599, ONE_BILLION-1); Chris@1262: compareTexts(rt.toText(false), "59:59.999"); Chris@1262: compareTexts(rt.toText(true), "59:59.999"); Chris@1262: Chris@1262: rt = RealTime::fromSeconds(3600 * 4 + 60 * 5 + 3 + 0.01); Chris@1262: compareTexts(rt.toText(false), "4:05:03.01"); Chris@1262: compareTexts(rt.toText(true), "4:05:03.010"); Chris@1262: Chris@1262: rt = RealTime::fromSeconds(-(3600 * 4 + 60 * 5 + 3 + 0.01)); Chris@1262: compareTexts(rt.toText(false), "-4:05:03.01"); Chris@1262: compareTexts(rt.toText(true), "-4:05:03.010"); Chris@1262: } Chris@1262: }; Chris@1262: Chris@1262: #endif Chris@1262: