Okay, I got it working, as far as I can tell; the patch against this
morning's source (Version 8516) is enclosed.
Details
* The packager copies a bunch of huge .svn directories containing .png
files into the applications. The enclosed packager script still
contains the RecursiveCopy routine that tries (unsucessfully) to
undo the damage. This issue is still unresolved.
* As noted in numerous places in my patch, the project's use of
#define always_inline
is problematic. That practice should end; for now it's worked
around through careful management of #include order and a
strategically-placed #undef always_inline
* You need Apple's FirewireSDK20 installed in its default location in
order to build.
* The changes I made in mythcontext.cpp were the only way I could get
commercial flagging to work. Otherwise the prefix path that gets
used is somewhere in the build disk image. The change in
jobqueue.cpp was half-finished and I'm not sure that it's necessary
at all, but when the backend stopped complaining about not being
able to launch the flagger I figured, "why mess with success?"
* Unless you know you have distcc working, you may need to uncomment
the '--disable-distcc' line in the packager script.
* You also might want to swap the activation of these two lines in the
packager:
# &Syscall([ '/usr/bin/make' ]) or die;
&Syscall([ '/usr/bin/make -j5' ]) or die;
* In the packager script the bug that causes the script to fail has
been resolved, but I commented out the line that unmounts the disk
image because it was more convenient for development.
Index: configure
===================================================================
--- configure (revision 8516)
+++ 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 8516)
+++ libs/libmythtv/firewirechannel.cpp (working copy)
@@ -10,19 +10,71 @@
#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)
+ : ChannelBase(parent),fw_opts(firewire_opts)
+#ifdef CONFIG_DARWIN
+ , device_controller(parent->DemandDeviceController())
+ , tunable_device(0)
+#endif
+ , isopen(false)
{
- isopen = false;
- fwhandle = NULL;
channelnames[0] = "MPEG2TS";
+#ifdef CONFIG_DARWIN
+ if (!this->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;
+ }
+
+ if (this->tunable_device->isOpened())
+ {
+ VERBOSE(VB_RECORD, QString("FirewireChannel: device already open") );
+ }
+ else
+ {
+ VERBOSE(VB_RECORD, QString("FirewireChannel: opening device") );
+ IOReturn err = this->tunable_device->openDevice();
+ if (err)
+ {
+ VERBOSE(VB_IMPORTANT,
+ QString("FireWireChannel: couldn't open tuner device: %1").arg(err));
+ 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 +94,55 @@
VERBOSE(VB_IMPORTANT, "FireWireChannel: internal channel "
"changer only supported by DCT-6200 and SA3250HD models");
}
+#endif
}
}
FirewireChannel::~FirewireChannel(void)
{
+#ifdef CONFIG_DARWIN
+ if (this->isopen)
+ this->tunable_device->closeDevice();
+#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 (!this->isopen)
+ return true;
+
+ // 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: %1").arg((int)err));
+ VERBOSE(VB_GENERAL, QString("Ignoring error per apple example"));
+ // 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 +210,7 @@
return false;
}
return true;
+#endif
}
bool FirewireChannel::Open()
Index: libs/libmythtv/jobqueue.cpp
===================================================================
--- libs/libmythtv/jobqueue.cpp (revision 8516)
+++ libs/libmythtv/jobqueue.cpp (working copy)
@@ -2008,7 +2008,13 @@
gContext->LogEntry("commflag", LP_NOTICE, msg, logDesc);
int breaksFound = 0;
- QString path = gContext->GetInstallPrefix() + "/bin/mythcommflag";
+ QString path = gContext->GetInstallPrefix()
+#ifdef CONFIG_DARWIN
+
+#else
+ + "/bin/mythcommflag"
+#endif
+ ;
QString cmd = QString("%1 -j %2 -V %3")
.arg(path).arg(jobID).arg(print_verbose_messages);
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro (revision 8516)
+++ 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 8516)
+++ 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/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp (revision 8516)
+++ libs/libmythtv/tv_rec.cpp (working copy)
@@ -68,6 +68,13 @@
#include "dbox2channel.h"
#endif
+#ifdef CONFIG_DARWIN
+// This include and its associated #undef must come last to avoid
+// interfering with the bogus #define always_inline used by MythTV.
+# undef always_inline
+# include <AVCVideoServices/AVCVideoServices.h>
+#endif
+
#define LOC QString("TVRec(%1): ").arg(cardid)
#define LOC_ERR QString("TVRec(%1) Error: ").arg(cardid)
@@ -124,6 +131,9 @@
tvchain(NULL),
// RingBuffer info
ringBuffer(NULL), rbFilePrefix(""), rbFileExt("mpg")
+#ifdef CONFIG_DARWIN
+ , device_controller(NULL)
+#endif
{
}
@@ -284,6 +294,10 @@
dummyRecorder = NULL;
}
+#ifdef CONFIG_DARWIN
+ AVS::DestroyAVCDeviceController(this->device_controller);
+#endif
+
SetRingBuffer(NULL);
}
@@ -3690,9 +3704,28 @@
return true;
}
+#ifdef CONFIG_DARWIN
+AVS::AVCDeviceController* TVRec::DemandDeviceController() const
+{
+ if (!this->device_controller)
+ {
+ IOReturn err = AVS::CreateAVCDeviceController(&this->device_controller);
+
+ if (err)
+ {
+ VERBOSE(
+ VB_IMPORTANT,
+ LOC_ERR + QString("unable to open device controller: ").arg(err));
+ }
+ }
+ return this->device_controller;
+}
+#endif
+
QString TuningRequest::toString(void) const
{
return QString("Program(%1) channel(%2) input(%3) flags(%4)")
.arg((program != 0) ? "yes" : "no").arg(channel).arg(input)
.arg(TVRec::FlagToString(flags));
}
+
Index: libs/libmythtv/firewirerecorder.cpp
===================================================================
--- libs/libmythtv/firewirerecorder.cpp (revision 8516)
+++ 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,211 @@
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 (UInt32 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)
+ {
+ // We'd check isMPEGDevice, but it turns out that for the
+ // DCT-6200, Apple doesn't set that flag. So instead we rule
+ // out DV devices.
+ // A more general OSX AVCRecorder class that also handles DV
+ // devices might not check either flag.
+ return d->isAttached && !d->isDVDevice
+// && (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
+ AVS::AVCDeviceController* device_controller = tvrec->DemandDeviceController();
+ if (!device_controller)
+ return false;
+
+ VERBOSE(VB_RECORD,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;
+ }
+
+ if (this->capture_device->isOpened())
+ {
+ VERBOSE(VB_RECORD, QString("Firewire: device already open") );
+ }
+ else
+ {
+ VERBOSE(VB_RECORD, QString("Firewire: opening device") );
+ IOReturn err = this->capture_device->openDevice();
+ if (err)
+ {
+ VERBOSE(VB_IMPORTANT,
+ QString("FireWire: couldn't open capture device: %1").arg(err));
+ this->Close();
+ return false;
+ }
+ }
+
+ VERBOSE(VB_GENERAL,QString("Firewire: Creating logger object"));
+
+ // If we don't set this immediately, Close() will refuse to clean
+ // up after whatever mess we make here
+ this->isopen = true;
+
+ 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 +309,7 @@
isopen = true;
fwfd = raw1394_get_fd(fwhandle);
+#endif
return true;
}
@@ -117,9 +317,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;
+
+ this->capture_device->closeDevice();
+#else
VERBOSE(VB_RECORD, "Firewire: releasing iec61883_mpeg2 object");
iec61883_mpeg2_close(fwmpeg);
@@ -133,12 +348,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 +363,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 +413,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 +445,24 @@
(void)profile;
}
-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 +480,10 @@
fwconnection = FIREWIRE_CONNECTION_P2P;
}
}
+#endif
}
+#ifndef CONFIG_DARWIN
QString FirewireRecorder::FirewireSpeedString (int speed) {
switch(speed) {
case RAW1394_ISO_SPEED_100:
@@ -247,6 +496,7 @@
return(QString("Invalid (%1)").arg(speed));
}
}
+#endif
// documented in recorderbase.cpp
bool FirewireRecorder::PauseAndWait(int timeout)
@@ -255,7 +505,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 +520,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/tv_rec.h
===================================================================
--- libs/libmythtv/tv_rec.h (revision 8516)
+++ libs/libmythtv/tv_rec.h (working copy)
@@ -14,6 +14,8 @@
#include "programinfo.h"
#include "tv.h"
+#include "mythconfig.h"
+
class QSocket;
class NuppelVideoRecorder;
class RingBuffer;
@@ -126,6 +128,13 @@
};
typedef MythDeque<TuningRequest> TuningQueue;
+#ifdef CONFIG_DARWIN
+namespace AVS
+{
+ class AVCDeviceController;
+}
+#endif
+
class TVRec : public QObject
{
friend class TuningRequest;
@@ -220,6 +229,10 @@
void RingBufferChanged(RingBuffer *rb, ProgramInfo *pginfo);
void RecorderPaused(void);
+#ifdef CONFIG_DARWIN
+ AVS::AVCDeviceController* DemandDeviceController() const;
+#endif
+
public slots:
void SignalMonitorAllGood() { triggerEventLoop.wakeAll(); }
void SetPMTObject(const PMTObject*)
@@ -357,6 +370,10 @@
QString rbFilePrefix;
QString rbFileExt;
+#ifdef CONFIG_DARWIN
+ mutable AVS::AVCDeviceController* device_controller;
+#endif
+
public:
static const uint kEITScanStartTimeout;
static const uint kSignalMonitoringRate;
Index: libs/libmythtv/firewirerecorder.h
===================================================================
--- libs/libmythtv/firewirerecorder.h (revision 8516)
+++ 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,19 @@
public:
FirewireRecorder(TVRec *rec) :
DTVRecorder(rec, "FirewireRecorder"),
- fwport(-1), fwchannel(-1), fwspeed(-1), fwbandwidth(-1),
+#ifdef CONFIG_DARWIN
+ 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 +71,37 @@
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::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/libmyth/mythcontext.cpp
===================================================================
--- libs/libmyth/mythcontext.cpp (revision 8516)
+++ libs/libmyth/mythcontext.cpp (working copy)
@@ -290,20 +290,20 @@
QDir prefixDir(appPath.left(appPath.findRev("/")));
#endif
- if (QDir(m_installprefix).isRelative())
+ if (prefixDir.path().contains(".app/Contents/MacOS"))
{
+ prefixDir.cd("../Resources");
+ if (QDir(prefixDir.canonicalPath() + "/share").exists())
+ m_installprefix = prefixDir.canonicalPath();
+ }
+ else if (QDir(m_installprefix).isRelative())
+ {
// If the PREFIX is relative, evaluate it relative to our
// executable directory. This can be fragile on Unix, so
// use relative PREFIX values with care.
prefixDir.cd(m_installprefix);
m_installprefix = prefixDir.canonicalPath();
}
- else if (prefixDir.path().contains(".app/Contents/MacOS"))
- {
- prefixDir.cd("../Resources");
- if (QDir(prefixDir.canonicalPath() + "/share").exists())
- m_installprefix = prefixDir.canonicalPath();
- }
VERBOSE(VB_ALL, QString("Using runtime prefix = %1")
.arg(m_installprefix));
}
Index: libs/libavcodec/libpostproc/postprocess.c
===================================================================
--- libs/libavcodec/libpostproc/postprocess.c (revision 8516)
+++ 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 8516)
+++ libs/libavutil/common.h (working copy)
@@ -67,6 +67,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 8516)
+++ 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: contrib/osx-packager.pl
===================================================================
--- contrib/osx-packager.pl (revision 8516)
+++ 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',
@@ -394,6 +424,8 @@
'mythtv'
=> [
'--prefix=' . $PREFIX,
+# '--disable-firewire',
+# '--disable-distcc',
],
);
@@ -522,7 +554,7 @@
# Configure
chdir($dirname);
- unless (-e '.osx-config')
+ unless (! $OPT{'forceconfigure'} && -e '.osx-config')
{
&Verbose("Configuring $sw");
my (@configure, $munge);
@@ -556,7 +588,7 @@
}
# Build and install
- unless (-e '.osx-built')
+ unless (! $OPT{'forcemake'} && -e '.osx-built')
{
&Verbose("Making $sw");
my (@make);
@@ -581,7 +613,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*";
@@ -677,10 +718,13 @@
&Verbose("Configuring $comp");
my @config = './configure';
push(@config, @{ $conf{$comp} }) if $conf{$comp};
+ # For debugging MythTV
+ # push @config, '--compile-type=debug';
if ( $comp eq 'mythtv' && $backend )
{
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 -j5' ]) 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.
@@ -756,12 +809,10 @@
# Get a fresh copy of the app
&Verbose("Building self-contained $target");
&Syscall([ 'rm', '-fr', $finalTarget ]) or die;
- &Syscall([ '/bin/cp', '-R',
- "$PREFIX/bin/$builtTarget.app",
- $finalTarget ]) or die;
+ &RecursiveCopy("$PREFIX/bin/$builtTarget.app", $finalTarget);
# write a custom Info.plist
- &FrontendPlist($finalTarget, $VERS);
+ &AppPlist($finalTarget, $builtTarget, $VERS);
# Make frameworks from Myth libraries
&Verbose("Installing frameworks into $target");
@@ -791,13 +842,11 @@
&Verbose("Installing resources into MythFrontend");
mkdir "$finalTarget/Contents/Resources";
mkdir "$finalTarget/Contents/Resources/lib";
- &Syscall([ '/bin/cp', '-R',
- "$PREFIX/lib/mythtv",
- "$finalTarget/Contents/Resources/lib" ]) or die;
+ &RecursiveCopy("$PREFIX/lib/mythtv",
+ "$finalTarget/Contents/Resources/lib");
mkdir "$finalTarget/Contents/Resources/share";
- &Syscall([ '/bin/cp', '-R',
- "$PREFIX/share/mythtv",
- "$finalTarget/Contents/Resources/share" ]) or die;
+ &RecursiveCopy( "$PREFIX/share/mythtv",
+ "$finalTarget/Contents/Resources/share" );
}
}
@@ -813,7 +862,18 @@
exit 0;
+sub RecursiveCopy
+{
+ my ($src, $dst) = @_;
+ &Syscall([ '/bin/cp', '-R', "$src", "$dst"]) or die;
+ my @files = map { chomp $_; $_ } `find . -name .svn`;
+ if (scalar @files)
+ {
+ &Syscall([ '/bin/rm', '-f', '-r', @files ]);
+ }
+}
+
######################################
## MakeFramework copies a dylib into a
## framework bundle.
@@ -880,14 +940,17 @@
######################################
-## FrontendPlist .
+## AppPlist .
######################################
-sub FrontendPlist
+sub AppPlist
{
- my ($path, $vers) = @_;
+ my ($path, $builttarget, $vers) = @_;
- &Verbose("Writing Info.plist for MythFrontend");
+ my $bundlename = $path;
+ $bundlename =~ s|^(.*)([^/]*)[.]app$|$2|;
+
+ &Verbose("Writing Info.plist for $bundlename");
my $plist;
$path .= '/Contents/Info.plist';
unless (open($plist, ">$path"))
@@ -901,11 +964,11 @@
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
- <string>mythfrontend</string>
+ <string>$builttarget</string>
<key>CFBundleIconFile</key>
<string>application.icns</string>
<key>CFBundleIdentifier</key>
- <string>org.mythtv.macx.mythfrontend</string>
+ <string>org.mythtv.macx.$builttarget</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
@@ -921,7 +984,7 @@
<key>CFBundleGetInfoString</key>
<string>$vers, MythTV project, www.mythtv.org</string>
<key>CFBundleName</key>
- <string>MythFrontend</string>
+ <string>$bundlename</string>
<key>NSHumanReadableCopyright</key>
<string>MythTV project, www.mythtv.org</string>
</dict>
@@ -939,7 +1002,7 @@
APPLMyth
END
close($plist);
-} # end FrontendPlist
+} # end AppPlist
######################################
## FindLibraryFile locates a dylib.
@@ -984,8 +1047,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 +1215,7 @@
my $device = HDImageDevice();
if ($device)
{
- System('hdiutil', 'detach', $device, '-force');
+# Syscall(['hdiutil', 'detach', $device, '-force']);
}
}
Index: setup/setup.pro
===================================================================
--- setup/setup.pro (revision 8516)
+++ setup/setup.pro (working copy)
@@ -1,5 +1,6 @@
include ( ../config.mak )
include ( ../settings.pro )
+include ( ../avcvideoservices.pro )
TEMPLATE = app
CONFIG += thread
Enjoy,
Dave
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
_______________________________________________
mythtv-dev mailing list
[email protected]
http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-dev