I'm still on vacation and away from my hardware (you wouldn't believe
what fun it is waiting for compilation on an old iBook G3), so I'm
unable to test it, but I now have code that builds and "should work."
If anyone would like to try it and report back, I'd be very grateful.
It would be useful to turn on whatever switch allows MythTV to do its
most verbose logging, so we can see what goes wrong. This code
ignores all the firewire port and channel settings, and instead uses
the first device it can find from which to capture MPEG for recording,
and the first device with tuning capability for channel changing. As
a bonus, it should be able to turn on your cable box via firewire if
the box has that capability.
The enclosed patch requires that you have Apple's FireWireSDK20
installed on the machine that does the build. Use the patched version
of contrib/osx-packager.pl with -enable-backend. The patch was made
against revision 8336, so I suppose you should checkout that revision
and use -nohead as well if you want to be sure of reproducing the same
environment I'm using. I'll probably try updating to head in the next
few days.
Enjoy, and of course, caveat emptor
;-).
Index: configure
===================================================================
--- configure (revision 8336)
+++ configure (working copy)
@@ -1996,7 +1996,7 @@
fi
-if test x"$firewire_cable_box" = x"yes" ; then
+if test x"$firewire_cable_box" = x"yes" -a x$darwin == x"" ; then
firewire_cable_box="no"
if has_library libiec61883 -a has_library libavc1394 ; then
if test x`which pkg-config 2>/dev/null` != x"" ; then
@@ -2692,6 +2692,16 @@
echo "#endif" >> $TMPH
if test "$optimize" = "small"; then
+ # This is completely broken; the MacOS headers (and, presumably,
+ # other legitimate headers) use constructs like:
+ #
+ # static __inline__ __attribute__((always_inline))
+ # return_type function_name() { ... }
+ #
+ # which naturally is disrupted by any attempt to #define
+ # always_inline. MythTv should use some other symbol for that
+ # purpose, preferably an ALL_UPPERCASE symbol beginning with MYTH_
+
echo "#define always_inline" >> $TMPH
fi
@@ -2797,7 +2807,9 @@
if test x"$firewire_cable_box" = x"yes" ; then
CCONFIG="$CCONFIG using_firewire"
- echo "CONFIG_FIREWIRE_LIBS=-lraw1394 -liec61883 -lavc1394" >> $MYTH_CONFIG_MAK
+ if test x"$darwin" != x"yes" ; then
+ echo "CONFIG_FIREWIRE_LIBS=-lraw1394 -liec61883 -lavc1394" >> $MYTH_CONFIG_MAK
+ fi
fi
if test x"$dbox2_dvb_box" = x"yes" ; then
Index: libs/libmythtv/firewirechannel.cpp
===================================================================
--- libs/libmythtv/firewirechannel.cpp (revision 8336)
+++ libs/libmythtv/firewirechannel.cpp (working copy)
@@ -10,19 +10,61 @@
#include "mythcontext.h"
#include "firewirechannel.h"
+#ifdef CONFIG_DARWIN
+# include "selectavcdevice.h"
+# undef always_inline
+# include <AVCVideoServices/AVCVideoServices.h>
+#endif
+
class TVRec;
+#ifdef CONFIG_DARWIN
+namespace
+{
+ bool find_tunable_device(AVS::AVCDevice* d)
+ {
+ return d->isAttached && d->hasMonitorOrTunerSubunit;
+ }
+}
+#endif
+
FirewireChannel::FirewireChannel(FireWireDBOptions firewire_opts, TVRec *parent)
: ChannelBase(parent),fw_opts(firewire_opts)
+#ifdef CONFIG_DARWIN
+ , device_controller(0)
+ , tunable_device(0)
+#endif
+ , isopen(false)
{
- isopen = false;
- fwhandle = NULL;
channelnames[0] = "MPEG2TS";
+#ifdef CONFIG_DARWIN
+ IOReturn err = AVS::CreateAVCDeviceController(&device_controller);
+ if (err)
+ {
+ VERBOSE(VB_IMPORTANT,
+ QString("FireWireChannel: unable to open device controller"));
+ return;
+ }
+#else
+ fwhandle = NULL;
+#endif
+
if (externalChanger[currentcapchannel].isEmpty())
{
+#ifdef CONFIG_DARWIN
+ this->tunable_device = SelectAVCDevice(device_controller, find_tunable_device);
+ if (!this->tunable_device)
+ {
+ VERBOSE(VB_IMPORTANT,
+ QString("FireWireChannel: unable to find an attached device that supports channel changes"));
+ return;
+ }
+
+ this->isopen = true;
+#else
if ((fw_opts.model == "DCT-6200") || (fw_opts.model == "SA3250HD"))
{
if ((fwhandle = raw1394_new_handle_on_port(fw_opts.port)) == NULL)
@@ -42,22 +84,53 @@
VERBOSE(VB_IMPORTANT, "FireWireChannel: internal channel "
"changer only supported by DCT-6200 and SA3250HD models");
}
+#endif
}
}
FirewireChannel::~FirewireChannel(void)
{
+#ifdef CONFIG_DARWIN
+ if (this->device_controller)
+ {
+ AVS::DestroyAVCDeviceController(device_controller);
+ }
+#else
if (isopen)
{
VERBOSE(VB_GENERAL,QString("FireWireChannel: releasing raw1394 handle"));
raw1394_destroy_handle(fwhandle);
}
+#endif
}
bool FirewireChannel::SetChannelByString(const QString &chan)
{
+ int channel = chan.toInt();
+#ifdef CONFIG_DARWIN
+ // If the tuner is off, try to turn it on.
+ UInt8 power_state;
+ IOReturn err = this->tunable_device->GetPowerState(&power_state);
+ if (err == kIOReturnSuccess && power_state == kAVCPowerStateOff)
+ {
+ tunable_device->SetPowerState(kAVCPowerStateOn);
+
+ // Give it time to power up.
+ usleep(2000000); // Sleep for two seconds
+ }
+
+ AVS::PanelSubunitController panel(tunable_device);
+ err = panel.Tune(channel);
+ if (err != kIOReturnSuccess)
+ {
+ VERBOSE(VB_GENERAL, QString("FirewireChannel: Tuning failed:").arg((int)err));
+ return false;
+ }
+ // Give it time to transition.
+ usleep(1000000); // Sleep for one second
+ return true;
+#else
int dig[3];
- int channel = chan.toInt();
quadlet_t cmd[3];
inputChannel[currentcapchannel] = chan;
@@ -125,6 +198,7 @@
return false;
}
return true;
+#endif
}
bool FirewireChannel::Open()
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro (revision 8336)
+++ libs/libmythtv/libmythtv.pro (working copy)
@@ -48,6 +48,12 @@
QMAKE_CXXFLAGS += -F/System/Library/Frameworks/$${FC}.framework/Frameworks
LIBS += -framework $$join(FWKS," -framework ")
+ using_backend {
+ AVSDIR = /Developer/FireWireSDK20/Examples/AVCVideoServices/Framework
+ QMAKE_CXXFLAGS += -F$${AVSDIR}
+ LIBS += -F$${AVSDIR} -framework AVCVideoServices
+ }
+
QMAKE_LFLAGS_SHLIB += -seg1addr 0xC9000000
}
@@ -307,6 +313,9 @@
HEADERS += frequencies.h
SOURCES += frequencies.c
+ macx:HEADERS += selectavcdevice.h
+ macx:SOURCES += selectavcdevice.cpp
+
DEFINES += USING_BACKEND
}
Index: libs/libmythtv/firewirechannel.h
===================================================================
--- libs/libmythtv/firewirechannel.h (revision 8336)
+++ libs/libmythtv/firewirechannel.h (working copy)
@@ -12,8 +12,19 @@
#include <qstring.h>
#include "tv_rec.h"
#include "channelbase.h"
-#include <libavc1394/avc1394.h>
+#include "mythconfig.h"
+
+#ifdef CONFIG_DARWIN
+namespace AVS
+{
+ class AVCDeviceController;
+ class AVCDevice;
+}
+#else
+# include <libavc1394/avc1394.h>
+#endif
+
using namespace std;
// 6200 defines for channel changes, taken from contrib/6200ch.c
@@ -60,8 +71,13 @@
private:
FireWireDBOptions fw_opts;
+#ifdef CONFIG_DARWIN
+ AVS::AVCDeviceController* device_controller;
+ AVS::AVCDevice* tunable_device;
+#else
nodeid_t fwnode;
raw1394handle_t fwhandle;
+#endif
bool isopen;
};
Index: libs/libmythtv/selectavcdevice.cpp
===================================================================
--- libs/libmythtv/selectavcdevice.cpp (revision 0)
+++ libs/libmythtv/selectavcdevice.cpp (revision 0)
@@ -0,0 +1,46 @@
+/**
+ * SelectAVCDevice
+ * Copyright (c) 2006 by Dave Abrahams
+ * Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include "mythconfig.h"
+
+#ifdef CONFIG_DARWIN
+# include "mythcontext.h"
+# include "selectavcdevice.h"
+# undef always_inline
+# include <AVCVideoServices/AVCVideoServices.h>
+
+AVS::AVCDevice* SelectAVCDevice(
+ AVS::AVCDeviceController* controller,
+ bool (*filter)(AVS::AVCDevice*)
+)
+{
+ VERBOSE(VB_GENERAL, QString("SelectAVCDevice:"));
+
+ for (unsigned n = CFArrayGetCount(controller->avcDeviceArray),
+ i = 0; i < n; ++i)
+ {
+ AVS::AVCDevice& d = *(AVS::AVCDevice*)CFArrayGetValueAtIndex(controller->avcDeviceArray, i);
+
+ VERBOSE(
+ VB_GENERAL,
+ QString("SelectAVCDevice: %1, format: %2, attached: %3, type: %4")
+ .arg(d.deviceName)
+ .arg(d.isDVDevice ? "DV" : d.isMPEGDevice ? "MPEG2-TS" : "unknown")
+ .arg(d.isAttached ? "yes" : "no")
+ .arg(d.hasTapeSubunit ? "tape" : d.hasMonitorOrTunerSubunit ? "tuner" : "unknown")
+ );
+
+ if (filter(&d))
+ {
+ VERBOSE(VB_GENERAL, QString("SelectAVCDevice: FOUND"));
+ return &d;
+ }
+ }
+ VERBOSE(VB_GENERAL, QString("SelectAVCDevice: NOT FOUND"));
+ return 0;
+}
+
+#endif // CONFIG_DARWIN
Index: libs/libmythtv/firewirerecorder.cpp
===================================================================
--- libs/libmythtv/firewirerecorder.cpp (revision 8336)
+++ libs/libmythtv/firewirerecorder.cpp (working copy)
@@ -18,6 +18,12 @@
#include "tspacket.h"
#include "tv_rec.h"
+#ifdef CONFIG_DARWIN
+# include "selectavcdevice.h"
+# undef always_inline
+# include <AVCVideoServices/AVCVideoServices.h>
+#endif
+
// callback function for libiec61883
int read_tspacket (unsigned char *tspacket, int /*len*/,
uint dropped, void *callback_data)
@@ -43,18 +49,194 @@
return 1;
}
-
+
void FirewireRecorder::deleteLater(void)
{
Close();
DTVRecorder::deleteLater();
}
+#ifdef CONFIG_DARWIN
+
+// Various message callbacks.
+void FirewireRecorder::MPEGNoData(void *pRefCon)
+{
+
+ FirewireRecorder* self = static_cast<FirewireRecorder*>(pRefCon);
+
+ VERBOSE(
+ VB_IMPORTANT,
+ QString("Firewire: No Input in %1 seconds (time)").arg(FIREWIRE_TIMEOUT));
+
+ self->_error = true;
+}
+
+namespace
+{
+ void (*my_mpeg_no_data)(void*);
+
+ IOReturn mpeg_no_data(void* pRefCon)
+ {
+ my_mpeg_no_data(pRefCon);
+ return 0;
+ }
+
+ void avs_log_message(char *pString)
+ {
+ // I don't know what QString does with plain char*, but surely it
+ // treats char const* as an NTBS.
+ char const* s = pString;
+
+ VERBOSE(VB_GENERAL,QString("Firewire MPEG2Receiver log: %1")
+ .arg(s));
+ }
+
+ void avs_message_received(
+ UInt32 msg, UInt32 param1, UInt32 param2, void *pRefCon)
+ {
+ (void)pRefCon;
+
+ VERBOSE(VB_RECORD,QString("Firewire MPEG2Receiver message: %1")
+ .arg(msg));
+
+ switch (msg)
+ {
+ case AVS::kMpeg2ReceiverAllocateIsochPort:
+ VERBOSE(
+ VB_RECORD,
+ QString("Firewire MPEG2Receiver allocated channel: %1, speed %2")
+ .arg(param2).arg(param1)
+ );
+ break;
+
+ case AVS::kMpeg2ReceiverDCLOverrun:
+ VERBOSE(
+ VB_IMPORTANT,
+ QString("Firewire MPEG2Receiver DCL Overrun")
+ );
+ break;
+
+ case AVS::kMpeg2ReceiverReceivedBadPacket:
+ VERBOSE(
+ VB_IMPORTANT,
+ QString("Firewire MPEG2Receiver Received Bad Packet ")
+ );
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ IOReturn tspacket_callback(UInt32 tsPacketCount, UInt32 **ppBuf,void *pRefCon)
+ {
+ for (int i = 0; i < tsPacketCount; ++i)
+ {
+ void* packet = ppBuf[i];
+ int ok = read_tspacket(
+ static_cast<unsigned char *>(packet),
+ AVS::kMPEG2TSPacketSize,
+ 0, // dropped
+ pRefCon);
+
+ // This is based on knowledge of what read_tspacket does --
+ // the only way it fails is with a NULL callback_data
+ // argument.
+ if (!ok)
+ return kIOReturnBadArgument;
+ }
+
+ return 0;
+ }
+
+ bool find_capture_device(AVS::AVCDevice* d)
+ {
+ // A more general OSX AVCRecorder class that also handles DV
+ // devices might not check isMPEGDevice
+ return d->isAttached && d->isMPEGDevice
+ && (d->hasTapeSubunit || d->hasMonitorOrTunerSubunit);
+ }
+
+ IOReturn device_controller_notification(AVS::AVCDeviceController *, void *, AVS::AVCDevice*)
+ {
+ return 0;
+ }
+}
+#endif
+
bool FirewireRecorder::Open() {
if (isopen)
return true;
+#ifdef CONFIG_DARWIN
+ VERBOSE(VB_GENERAL,QString("Firewire: Creating AVCDeviceController"));
+
+ IOReturn err = AVS::CreateAVCDeviceController(&device_controller, device_controller_notification, 0);
+ if (!device_controller)
+ {
+ VERBOSE(VB_IMPORTANT, QString("Firewire: Failed to create AVCDeviceController: %d").arg((int)err) );
+ return false;
+ }
+
+ // If we don't set this immediately, Close() will refuse to clean
+ // up after whatever mess we make here
+ this->isopen = true;
+
+ VERBOSE(VB_GENERAL,QString("Firewire: Looking for a device from which we can capture MPEG"));
+ this->capture_device = SelectAVCDevice(device_controller, find_capture_device);
+ if (!this->capture_device)
+ {
+ VERBOSE(VB_IMPORTANT, QString("Firewire: No suitable device found") );
+ this->Close();
+ return false;
+ }
+
+ VERBOSE(VB_GENERAL,QString("Firewire: Creating logger object"));
+ this->message_log = new AVS::StringLogger(avs_log_message);
+ if (!this->message_log)
+ {
+ VERBOSE(VB_IMPORTANT, QString("Firewire: Couldn't create logger") );
+ this->Close();
+ return false;
+ }
+
+ VERBOSE(VB_GENERAL,QString("Firewire: Creating MPEG-2 device stream"));
+
+ // This not only builds an MPEG2Receiver object but also starts dedicated real-time threads.
+ this->video_stream = capture_device->CreateMPEGReceiverForDevicePlug(
+ 0, // Plug number. Why is zero always OK? I
+ // don't know, but that's what Apple's
+ // examples do.
+ tspacket_callback,
+ this,
+ avs_message_received,
+ this,
+ this->message_log,
+ AVS::kCyclesPerReceiveSegment,
+ // Why multiply by 2 instead of using the default,
+ // kNumReceiveSegments? Because it's what Apple's only
+ // example of the use of this function does.
+ AVS::kNumReceiveSegments*2);
+
+ if (!this->video_stream)
+ {
+ VERBOSE(VB_IMPORTANT, QString("Firewire: Couldn't create MPEG-2 device stream") );
+ this->Close();
+ return false;
+ }
+
+ // We could set the channel to receive on, but it doesn't seem
+ // like we need to, and if the device is already transmitting it
+ // could lead to inefficiency because the device stream is smart
+ // enough to avoid allocating new bandwidth.
+
+ // Register a no-data notification callback
+ my_mpeg_no_data = &FirewireRecorder::MPEGNoData;
+ video_stream->pMPEGReceiver->registerNoDataNotificationCallback(
+ mpeg_no_data, this, FIREWIRE_TIMEOUT * 1000);
+
+#else
VERBOSE(VB_GENERAL,QString("Firewire: Initializing Port: %1, Node: %2, Speed: %3")
.arg(fwport)
.arg(fwnode)
@@ -110,6 +292,7 @@
isopen = true;
fwfd = raw1394_get_fd(fwhandle);
+#endif
return true;
}
@@ -117,9 +300,24 @@
{
if (!isopen)
return;
-
+
isopen = false;
+#ifdef CONFIG_DARWIN
+ if (this->video_stream)
+ {
+ VERBOSE(VB_RECORD, "Firewire: Stopping device stream");
+ this->capture_device->StopAVCDeviceStream(this->video_stream);
+ VERBOSE(VB_RECORD, "Firewire: Destroying device stream");
+ this->capture_device->DestroyAVCDeviceStream(this->video_stream);
+ this->video_stream = 0;
+ }
+
+ delete this->message_log;
+ this->message_log = 0;
+
+ AVS::DestroyAVCDeviceController(this->device_controller);
+#else
VERBOSE(VB_RECORD, "Firewire: releasing iec61883_mpeg2 object");
iec61883_mpeg2_close(fwmpeg);
@@ -133,12 +331,10 @@
VERBOSE(VB_RECORD, "Firewire: releasing raw1394 handle");
raw1394_destroy_handle(fwhandle);
+#endif
}
void FirewireRecorder::StartRecording(void) {
-
- struct timeval tv;
- fd_set rfds;
VERBOSE(VB_RECORD, QString("StartRecording"));
@@ -150,19 +346,37 @@
_request_recording = true;
_recording = true;
+#ifdef CONFIG_DARWIN
+ this->capture_device->StartAVCDeviceStream(this->video_stream);
+#else
+ struct timeval tv;
+ fd_set rfds;
+
iec61883_mpeg2_recv_start(fwmpeg,fwchannel);
+#endif
lastpacket = time(NULL);
while(_request_recording) {
if (PauseAndWait())
continue;
if (time(NULL) - lastpacket > FIREWIRE_TIMEOUT) {
- VERBOSE(VB_IMPORTANT, QString("Firewire: No Input in %1 seconds [P:%2 N:%3] (time)").arg(FIREWIRE_TIMEOUT).arg(fwport).arg(fwnode));
+#ifdef CONFIG_DARWIN
+ this->MPEGNoData(this);
+ this->capture_device->StopAVCDeviceStream(this->video_stream);
+#else
+ VERBOSE(
+ VB_IMPORTANT,
+ QString("Firewire: No Input in %1 seconds [P:%2 N:%3] (time)")
+ .arg(FIREWIRE_TIMEOUT).arg(fwport).arg(fwnode));
iec61883_mpeg2_recv_stop(fwmpeg);
_error = true;
+#endif
return;
}
+#ifdef CONFIG_DARWIN
+ usleep(100);
+#else
FD_ZERO (&rfds);
FD_SET (fwfd, &rfds);
tv.tv_sec = FIREWIRE_TIMEOUT;
@@ -182,10 +396,17 @@
_error = true;
return;
}
+#endif
}
+#ifdef CONFIG_DARWIN
+ VERBOSE(VB_RECORD, "Firewire: Stopping video stream");
+ this->capture_device->StopAVCDeviceStream(this->video_stream);
+#else
iec61883_mpeg2_recv_stop(fwmpeg);
+#endif
FinishRecording();
+
_recording = false;
}
@@ -207,15 +428,24 @@
(void)ispip;
}
-void FirewireRecorder::SetOption(const QString &name, const QString &value) {
-
+void FirewireRecorder::SetOption(const QString &name, const QString &value)
+{
+#ifdef CONFIG_DARWIN
+ (void)name;
+ (void)value;
+#else
if (name == "model") {
fwmodel = value;
}
+#endif
}
-void FirewireRecorder::SetOption(const QString &name, int value) {
-
+void FirewireRecorder::SetOption(const QString &name, int value)
+{
+#ifdef CONFIG_DARWIN
+ (void)name;
+ (void)value;
+#else
if (name == "port") {
fwport = value;
} else if (name == "node") {
@@ -233,8 +463,10 @@
fwconnection = FIREWIRE_CONNECTION_P2P;
}
}
+#endif
}
+#ifndef CONFIG_DARWIN
QString FirewireRecorder::FirewireSpeedString (int speed) {
switch(speed) {
case RAW1394_ISO_SPEED_100:
@@ -247,6 +479,7 @@
return(QString("Invalid (%1)").arg(speed));
}
}
+#endif
// documented in recorderbase.cpp
bool FirewireRecorder::PauseAndWait(int timeout)
@@ -255,7 +488,12 @@
{
if (!paused)
{
+#ifdef CONFIG_DARWIN
+ VERBOSE(VB_RECORD, "Firewire: Stopping video stream");
+ this->capture_device->StopAVCDeviceStream(this->video_stream);
+#else
iec61883_mpeg2_recv_stop(fwmpeg);
+#endif
paused = true;
pauseWait.wakeAll();
if (tvrec)
@@ -265,7 +503,12 @@
}
if (!request_pause && paused)
{
+#ifdef CONFIG_DARWIN
+ VERBOSE(VB_RECORD, "Firewire: Restarting video stream");
+ this->capture_device->StartAVCDeviceStream(this->video_stream);
+#else
iec61883_mpeg2_recv_start(fwmpeg, fwchannel);
+#endif
paused = false;
}
return paused;
Index: libs/libmythtv/selectavcdevice.h
===================================================================
--- libs/libmythtv/selectavcdevice.h (revision 0)
+++ libs/libmythtv/selectavcdevice.h (revision 0)
@@ -0,0 +1,23 @@
+/**
+ * SelectAVCDevice
+ * Copyright (c) 2006 by Dave Abrahams
+ * Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef LIBMYTHTV_SELECTAVCDEVICE_H_
+# define LIBMYTHTV_SELECTAVCDEVICE_H_
+
+# include "mythconfig.h"
+
+# ifdef CONFIG_DARWIN
+# undef always_inline
+# include <AVCVideoServices/AVCVideoServices.h>
+
+AVS::AVCDevice* SelectAVCDevice(
+ AVS::AVCDeviceController*,
+ bool (*)(AVS::AVCDevice*)
+);
+
+# endif // CONFIG_DARWIN
+
+#endif LIBMYTHTV_SELECTAVCDEVICE_H_
Index: libs/libmythtv/firewirerecorder.h
===================================================================
--- libs/libmythtv/firewirerecorder.h (revision 8336)
+++ libs/libmythtv/firewirerecorder.h (working copy)
@@ -9,9 +9,22 @@
#include "dtvrecorder.h"
#include "mpeg/tspacket.h"
-#include <libraw1394/raw1394.h>
-#include <libiec61883/iec61883.h>
+#include "mythconfig.h"
+
+#ifdef CONFIG_DARWIN
+namespace AVS
+{
+ class AVCDeviceController;
+ class AVCDevice;
+ class StringLogger;
+ class AVCDeviceStream;
+}
+#else
+# include <libraw1394/raw1394.h>
+# include <libiec61883/iec61883.h>
+#endif
+
#include <time.h>
#define FIREWIRE_TIMEOUT 15
@@ -32,10 +45,20 @@
public:
FirewireRecorder(TVRec *rec) :
DTVRecorder(rec, "FirewireRecorder"),
- fwport(-1), fwchannel(-1), fwspeed(-1), fwbandwidth(-1),
+#ifdef CONFIG_DARWIN
+ device_controller(NULL),
+ capture_device(NULL),
+ message_log(NULL),
+ video_stream(NULL),
+#else
+ fwport(-1),
+ fwchannel(-1), fwspeed(-1), fwbandwidth(-1),
fwfd(-1), fwconnection(FIREWIRE_CONNECTION_P2P),
fwoplug(-1), fwiplug(-1), fwmodel(""), fwnode(0),
- fwhandle(NULL), fwmpeg(NULL), isopen(false), lastpacket(0) {;}
+ fwhandle(NULL), fwmpeg(NULL),
+#endif
+ isopen(false), lastpacket(0)
+ {;}
~FirewireRecorder() { Close(); }
@@ -49,21 +72,38 @@
void SetOption(const QString &name, const QString &value);
void SetOption(const QString &name, int value);
+#ifndef CONFIG_DARWIN
QString FirewireSpeedString(int speed);
+#endif
bool PauseAndWait(int timeout = 100);
public slots:
void deleteLater(void);
-
+
private:
void Close(void);
- int fwport, fwchannel, fwspeed, fwbandwidth, fwfd, fwconnection;
+
+#ifdef CONFIG_DARWIN
+ static void MPEGNoData(void*);
+
+ AVS::AVCDeviceController* device_controller;
+ AVS::AVCDevice* capture_device;
+ AVS::StringLogger* message_log;
+ AVS::AVCDeviceStream* video_stream;
+#else
+ int fwport;
+ int fwchannel;
+#endif
+
+#ifndef CONFIG_DARWIN
+ int fwspeed, fwbandwidth, fwfd, fwconnection;
int fwoplug, fwiplug;
QString fwmodel;
nodeid_t fwnode;
raw1394handle_t fwhandle;
iec61883_mpeg2_t fwmpeg;
+#endif
bool isopen;
time_t lastpacket;
};
Index: libs/libavcodec/libpostproc/postprocess.c
===================================================================
--- libs/libavcodec/libpostproc/postprocess.c (revision 8336)
+++ libs/libavcodec/libpostproc/postprocess.c (working copy)
@@ -113,6 +113,15 @@
#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
# define attribute_used __attribute__((used))
+// This is completely broken; the MacOS headers (and, presumably,
+// other legitimate headers) use constructs like:
+//
+// static __inline__ __attribute__((always_inline))
+// return_type function_name() { ... }
+//
+// which naturally is disrupted by any attempt to #define
+// always_inline. MythTv should use some other symbol for that
+// purpose, preferably an ALL_UPPERCASE symbol beginning with MYTH_
# define always_inline __attribute__((always_inline)) inline
#else
# define attribute_used
Index: libs/libavutil/common.h
===================================================================
--- libs/libavutil/common.h (revision 8336)
+++ libs/libavutil/common.h (working copy)
@@ -63,6 +63,16 @@
#ifndef always_inline
#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
+// This is completely broken; the MacOS headers (and, presumably,
+// other legitimate headers) use constructs like:
+//
+// static __inline__ __attribute__((always_inline))
+// return_type function_name() { ... }
+//
+// which naturally is disrupted by any attempt to #define
+// always_inline. MythTv should use some other symbol for that
+// purpose, preferably an ALL_UPPERCASE symbol beginning with MYTH_
+
# define always_inline __attribute__((always_inline)) inline
#else
# define always_inline inline
Index: programs/programs-libs.pro
===================================================================
--- programs/programs-libs.pro (revision 8336)
+++ programs/programs-libs.pro (working copy)
@@ -1,3 +1,4 @@
+include ( ../../avcvideoservices.pro )
INCLUDEPATH += ../../libs/ ../../libs/libmyth ../../libs/libmythtv ../..
INCLUDEPATH += ../../libs/libavutil ../../libs/libavformat ../../libs/libavcodec
@@ -22,4 +23,3 @@
DEPENDPATH += ../../libs/libmyth ../../libs/libmythtv ../../libs/libsavcodec
DEPENDPATH += ../../libs/libavutil ../../libs/libavformat
-
Index: setup/setup.pro
===================================================================
--- setup/setup.pro (revision 8336)
+++ setup/setup.pro (working copy)
@@ -1,5 +1,6 @@
include ( ../config.mak )
include ( ../settings.pro )
+include ( ../avcvideoservices.pro )
TEMPLATE = app
CONFIG += thread
Index: contrib/osx-packager.pl
===================================================================
--- contrib/osx-packager.pl (revision 8336)
+++ contrib/osx-packager.pl (working copy)
@@ -153,7 +153,7 @@
# },
{
'url'
- => 'ftp://ftp.iasi.roedu.net/mirrors/ftp.trolltech.com/qt/sources/qt-mac-free-3.3.4.tar.gz',
+ => 'ftp://ftp.iasi.roedu.net/mirrors/ftp.trolltech.com/qt/sources/qt-mac-free-3.3.5.tar.gz',
'conf-cmd'
=> 'echo yes | ./configure',
'conf'
@@ -185,7 +185,13 @@
=> [
'sub-src',
'qmake-install',
- 'moc-install'
+ 'moc-install',
+
+ # we need this. If the library isn't copied to
+ # $PREFIX/build/lib then it gets its references modified in
+ # place. That will screw up linking the next time around, as
+ # the references can't be found in the expected location.
+ 'src-install'
],
},
@@ -205,6 +211,22 @@
=> [
'--disable-nls',
],
+ 'post-conf'
+ # correct a bug that prevents compilation. This patch is already
+ # in the exif developers' CVS repository. Why they haven't
+ # released a new version with the fix, I don't know.
+ => 'echo "--- libexif/libexif/libexif/exif-utils.c2005/03/10 20:48:211.10
++++ libexif/libexif/libexif/exif-utils.c2005/03/31 12:24:311.11
+@@ -83,7 +83,7 @@
+ }
+ }
+
+-static ExifSShort
++ExifSShort
+ exif_get_sshort (const unsigned char *buf, ExifByteOrder order)
+ {
+ if (!buf) return 0;
+" | patch -u --verbose libexif/exif-utils.c'
},
);
@@ -227,6 +249,10 @@
-distclean throw away all intermediate files and exit
-thirdclean do a clean rebuild of third party packages
-thirdskip don't rebuild the third party packages
+ -skip don't rebuild MythTV
+ -tarball make a tarball of the build directory ($PREFIX)
+ -forcemake re-run all make steps
+ -forceconfigure re-run all configure steps
-clean do a clean rebuild of MythTV
-svnbranch <str> build a specified Subversion branch, instead of HEAD
-svnrev <str> build a specified Subversion revision, instead of HEAD
@@ -292,6 +318,10 @@
'distclean',
'thirdclean',
'thirdskip',
+ 'skip',
+ 'tarball',
+ 'forcemake',
+ 'forceconfigure',
'clean',
'svnbranch=s',
'svnrev=s',
@@ -390,10 +420,14 @@
'--enable-mythnews',
'--disable-mythphone',
'--enable-mythweather',
+ # The latest has failed to compile without this option
+ '--enable-new-exif',
],
'mythtv'
=> [
'--prefix=' . $PREFIX,
+# '--disable-firewire',
+ '--disable-distcc',
],
);
@@ -522,7 +556,7 @@
# Configure
chdir($dirname);
- unless (-e '.osx-config')
+ unless (! $OPT{'forceconfigure'} && -e '.osx-config')
{
&Verbose("Configuring $sw");
my (@configure, $munge);
@@ -556,7 +590,7 @@
}
# Build and install
- unless (-e '.osx-built')
+ unless (! $OPT{'forcemake'} && -e '.osx-built')
{
&Verbose("Making $sw");
my (@make);
@@ -581,7 +615,16 @@
### build MythTV
-
+if ( $OPT{'skip'} )
+{
+ &Verbose("Using previous install of MythTV");
+ if (-e "$PREFIX/../build.tar.gz")
+ {
+ &Syscall("cd $PREFIX/.. && tar xzf build.tar.gz");
+ }
+}
+else
+{
# Clean any previously installed libraries
&Verbose("Cleaning previous installs of MythTV");
my @mythlibs = glob "$PREFIX/lib/libmyth*";
@@ -681,6 +724,7 @@
{
push @config, '--enable-backend'
}
+ push @config, '"'
&Syscall([ @config ]) or die;
}
&Verbose("Running qmake for $comp");
@@ -719,7 +763,8 @@
}
&Verbose("Making $comp");
- &Syscall([ '/usr/bin/make' ]) or die;
+ &Syscall([ '/usr/bin/make' ]) or die;
+# &Syscall([ '/usr/bin/make -j2' ]) or die;
# install
# This requires a change from the compiled-in relative
# PREFIX to our absolute path of the temp install location.
@@ -732,14 +777,22 @@
&Verbose("Installing $comp");
&Syscall([ '/usr/bin/make',
'install' ]) or die;
+ }
}
+symlink("$SRCDIR/myth-svn/mythtv/libs", "$PREFIX/lib/mythtv");
+
### Build version string
our $VERS = `find $PREFIX/lib -name 'libmyth-[0-9].[0-9][0-9].[0-9].dylib'`;
chomp $VERS;
$VERS =~ s/^.*\-(.*)\.dylib$/$1/s;
$VERS .= '.' . $OPT{'version'} if $OPT{'version'};
+if ( $OPT{'tarball'} )
+{
+ &Syscall("tar czf $PREFIX/../build.tar.gz $PREFIX");
+}
+
### Create each package.
### Note that this is a bit of a waste of disk space,
### because there are now multiple copies of each library.
@@ -984,8 +1037,11 @@
chomp $dep;
$dep =~ s/\s+(.*) \(.*\)$/$1/;
+ # /usr/lib/libstdc++, for example, contains quantifiers that must be escaped
+ $dep =~ s/([+*?])/\\$1/;
+
# otool sometimes lists the framework as depending on itself
- next if ($file =~ m,/Versions/A/$dep,);
+ next if ($file =~ m|/Versions/A/$dep|);
# Any dependency which is already package relative can be ignored
next if $dep =~ m/[EMAIL PROTECTED]/;
@@ -1149,7 +1205,7 @@
my $device = HDImageDevice();
if ($device)
{
- System('hdiutil', 'detach', $device, '-force');
+ Syscall(['hdiutil', 'detach', $device, '-force']);
}
}
Index: avcvideoservices.pro
===================================================================
--- avcvideoservices.pro (revision 0)
+++ avcvideoservices.pro (revision 0)
@@ -0,0 +1,9 @@
+macx {
+ AVS_DIR = /Developer/FireWireSDK20/Examples/AVCVideoServices/Framework
+ LIBS += -F$${AVS_DIR} -framework AVCVideoServices
+ FWKS = $(DESTDIR)../Frameworks
+
+ QMAKE_POST_LINK= \
+ ( test -d $$FWKS || $(MKDIR) $$FWKS ) \
+ && cp -r $${AVS_DIR}/AVCVideoServices.framework $$FWKS
+}
svn: Working copy 'config' is missing or not locked
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
_______________________________________________
mythtv-dev mailing list
[email protected]
http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-dev