38 changes: 38 additions & 0 deletions mythtv/libs/libmythtv/videosource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2855,6 +2855,42 @@ class InputPriority : public SpinBoxSetting, public CardInputDBStorage
};
};

class ScheduleOrder : public SpinBoxSetting, public CardInputDBStorage
{
public:
ScheduleOrder(const CardInput &parent, int _value) :
SpinBoxSetting(this, 0, 99, 1),
CardInputDBStorage(this, parent, "schedorder")
{
setLabel(QObject::tr("Schedule order"));
setValue(_value);
setHelpText(QObject::tr("If priorities and other factors are equal "
"the scheduler will choose the available "
"input with the lowest, non-zero value. "
"Setting this value to zero will make the "
"input unavailable to the scheduler."));
};
};

class LiveTVOrder : public SpinBoxSetting, public CardInputDBStorage
{
public:
LiveTVOrder(const CardInput &parent, int _value) :
SpinBoxSetting(this, 0, 99, 1),
CardInputDBStorage(this, parent, "livetvorder")
{
setLabel(QObject::tr("Live TV order"));
setValue(_value);
setHelpText(QObject::tr("When entering Live TV, the available, local "
"input with the lowest, non-zero value will "
"be used. If no local inputs are available, "
"the available, remote input with the lowest, "
"non-zero value will be used. "
"Setting this value to zero will make the "
"input unavailable to live TV."));
};
};

class DishNetEIT : public CheckBoxSetting, public CardInputDBStorage
{
public:
Expand Down Expand Up @@ -2943,6 +2979,8 @@ CardInput::CardInput(bool isDTVcard, bool isDVBcard,

interact->setLabel(QObject::tr("Interactions between inputs"));
interact->addChild(new InputPriority(*this));
interact->addChild(new ScheduleOrder(*this, _cardid));
interact->addChild(new LiveTVOrder(*this, _cardid));

TransButtonSetting *ingrpbtn = new TransButtonSetting("newgroup");
ingrpbtn->setLabel(QObject::tr("Create a New Input Group"));
Expand Down
55 changes: 26 additions & 29 deletions mythtv/programs/mythbackend/mainserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3494,48 +3494,45 @@ void MainServer::HandleGetFreeRecorder(PlaybackSock *pbs)

EncoderLink *encoder = NULL;
QString enchost;

bool lastcard = false;

if (gCoreContext->GetSetting("LastFreeCard", "0") == "1")
lastcard = true;
QString besthost;
uint bestorder = 0;

QMap<int, EncoderLink *>::Iterator iter = encoderList->begin();
for (; iter != encoderList->end(); ++iter)
{
EncoderLink *elink = *iter;

if (!lastcard)
{
if (elink->IsLocal())
enchost = gCoreContext->GetHostName();
else
enchost = elink->GetHostName();
if (elink->IsLocal())
enchost = gCoreContext->GetHostName();
else
enchost = elink->GetHostName();

if (enchost == pbshost && elink->IsConnected() &&
!elink->IsTunerLocked() &&
!elink->GetFreeInputs(excluded_cardids).empty())
LOG(VB_RECORD, LOG_INFO,
QString("Checking card %1. Best card so far %2")
.arg(iter.key()).arg(retval));

if (!elink->IsConnected() || elink->IsTunerLocked() ||
(besthost == pbshost && enchost != pbshost))
continue;

vector<InputInfo> inputs = elink->GetFreeInputs(excluded_cardids);

for (uint i = 0; i < inputs.size(); ++i)
{
if (!encoder || inputs[i].livetvorder < bestorder ||
(besthost != pbshost && enchost == pbshost))
{
encoder = elink;
retval = iter.key();
LOG(VB_RECORD, LOG_INFO, QString("Card %1 is local.")
.arg(iter.key()));
break;
encoder = elink;
bestorder = inputs[i].livetvorder;
besthost = enchost;
}
}

if ((retval == -1 || lastcard) && elink->IsConnected() &&
!elink->IsTunerLocked() &&
!elink->GetFreeInputs(excluded_cardids).empty())
{
encoder = elink;
retval = iter.key();
}
LOG(VB_RECORD, LOG_INFO,
QString("Checking card %1. Best card so far %2")
.arg(iter.key()).arg(retval));
}

LOG(VB_RECORD, LOG_INFO,
QString("Best card is %1").arg(retval));

strlist << QString::number(retval);

if (encoder)
Expand Down
12 changes: 9 additions & 3 deletions mythtv/programs/mythbackend/scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,9 @@ static bool comp_priority(RecordingInfo *a, RecordingInfo *b)
return a->GetRecordingStartTime() < b->GetRecordingStartTime();
}

if (a->GetRecordingPriority2() != b->GetRecordingPriority2())
return a->GetRecordingPriority2() < b->GetRecordingPriority2();

if (a->GetInputID() != b->GetInputID())
return a->GetInputID() < b->GetInputID();

Expand Down Expand Up @@ -1417,6 +1420,7 @@ void Scheduler::PruneRedundants(void)
!lastp->IsSameTimeslot(*p))
{
lastp = p;
lastp->SetRecordingPriority2(0);
++i;
}
else
Expand Down Expand Up @@ -3769,7 +3773,7 @@ void Scheduler::AddNewRecords(void)
" p.subtitletypes+0, p.audioprop+0, RECTABLE.storagegroup, "//40-42
" capturecard.hostname, recordmatch.oldrecstatus, "
" RECTABLE.avg_delay, "//43-45
" oldrecstatus.future, " //46
" oldrecstatus.future, cardinput.schedorder, " //46-47
+ pwrpri + QString(
"FROM recordmatch "
"INNER JOIN RECTABLE ON (recordmatch.recordid = RECTABLE.recordid) "
Expand Down Expand Up @@ -3874,6 +3878,7 @@ void Scheduler::AddNewRecords(void)
result.value(39).toUInt(),//videoproperties
result.value(41).toUInt(),//audioproperties
result.value(46).toInt());//future
p->SetRecordingPriority2(result.value(47).toInt()); // schedorder

if (!p->future && !p->IsReactivated() &&
p->oldrecstatus != rsAborted &&
Expand All @@ -3890,7 +3895,7 @@ void Scheduler::AddNewRecords(void)

p->SetRecordingPriority(
p->GetRecordingPriority() + recTypeRecPriorityMap[p->GetRecordingRuleType()] +
result.value(47).toInt() +
result.value(48).toInt() +
((autopriority) ?
autopriority - (result.value(45).toInt() * autostrata / 200) : 0));

Expand Down Expand Up @@ -3920,7 +3925,8 @@ void Scheduler::AddNewRecords(void)

RecStatusType newrecstatus = p->GetRecordingStatus();
// Check for rsOffLine
if ((doRun || specsched) && !cardMap.contains(p->GetCardID()))
if ((doRun || specsched) &&
(!cardMap.contains(p->GetCardID()) || !p->GetRecordingPriority2()))
newrecstatus = rsOffLine;

// Check for rsTooManyRecordings
Expand Down
7 changes: 5 additions & 2 deletions mythtv/programs/mythbackend/services/capture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,9 @@ int Capture::AddCardInput ( const uint nCardId,
const QString &sDisplayName,
bool bDishnetEIT,
const uint nRecPriority,
const uint nQuicktune)
const uint nQuicktune,
const uint nSchedOrder,
const uint nLiveTVOrder)
{
if ( nCardId < 1 || nSourceId < 1 || sInputName.isEmpty() )
throw( QString( "This API requires at least a card ID, a source ID, "
Expand All @@ -292,7 +294,8 @@ int Capture::AddCardInput ( const uint nCardId,
int nResult = CardUtil::CreateCardInput(nCardId, nSourceId, sInputName,
sExternalCommand, sChangerDevice, sChangerModel,
sHostName, sTuneChan, sStartChan, sDisplayName,
bDishnetEIT, nRecPriority, nQuicktune);
bDishnetEIT, nRecPriority, nQuicktune, nSchedOrder,
nLiveTVOrder);

return nResult;
}
Expand Down
4 changes: 3 additions & 1 deletion mythtv/programs/mythbackend/services/capture.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ class Capture : public CaptureServices
const QString &DisplayName,
bool DishnetEIT,
const uint RecPriority,
const uint Quicktune);
const uint Quicktune,
const uint SchedOrder,
const uint LiveTVOrder);

bool UpdateCardInput ( int CardInputId,
const QString &Setting,
Expand Down
13 changes: 0 additions & 13 deletions mythtv/programs/mythfrontend/globalsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2247,18 +2247,6 @@ static HostComboBox *LongChannelFormat()
return gc;
}

static GlobalCheckBox *LastFreeCard()
{
GlobalCheckBox *bc = new GlobalCheckBox("LastFreeCard");
bc->setLabel(QObject::tr("Avoid conflicts between Live TV and "
"scheduled shows"));
bc->setValue(false);
bc->setHelpText(QObject::tr("If enabled, Live TV will choose a tuner card "
"that is less likely to have scheduled recordings "
"rather than the best card available."));
return bc;
}

static GlobalCheckBox *LiveTVPriority()
{
GlobalCheckBox *bc = new GlobalCheckBox("LiveTVPriority");
Expand Down Expand Up @@ -3484,7 +3472,6 @@ GeneralSettings::GeneralSettings()
general->addChild(ChannelOrdering());
general->addChild(ChannelFormat());
general->addChild(LongChannelFormat());
general->addChild(LastFreeCard());
general->addChild(LiveTVPriority());
addChild(general);

Expand Down