Skip to content

Commit 852b80a

Browse files
author
Paul Harrison
committed
Add channel grouping feature that allows you to create groups of channels to
help to find a channel while in live tv or the EPG. * There's a new 'Channel Groups' settings page where you can add/delete the groups and also to change what channels appear in a group. * While watching live tv you can select which channel group is active from the menu. When a group is selected and the current channel isn't in the group then the player will switch to the first channel in that group. Browsing in the OSD and changing channels will be restricted to channels from the current group. * If you switch to the EPG from live tv the EPG will only show channels from the current channel group. * In the EPG you can change the current group from the menu or you can cycle though the groups by pressing NEXFAV ('/'). * If you are viewing all the channels in the EPG you add the current channel to a channel group from the menu or by pressing TOGGLEFAV ('?'). * If you are viewing channels in a group in the EPG you can remove the current channel from the group via the menu or by pressing TOGGLEFAV ('?'). * A channel group called 'Favorites' is created and any existing favorites are placed in that group. * Bumps the protocol version to 45. Thanks to all who contributed to the patch on the ticket. I've made a few changes to the patch so any bugs are mine. Closes #199. git-svn-id: http://svn.mythtv.org/svn/trunk@20523 7dbf422c-18fa-0310-86e9-fd20926502f2
1 parent d14b214 commit 852b80a

31 files changed

+1182
-190
lines changed

mythtv/bindings/perl/MythTV.pm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ package MythTV;
101101

102102
# MYTH_PROTO_VERSION is defined in libmyth in mythtv/libs/libmyth/mythcontext.h
103103
# and should be the current MythTV protocol version.
104-
our $PROTO_VERSION = 44;
104+
our $PROTO_VERSION = 45;
105105

106106
# NUMPROGRAMLINES is defined in mythtv/libs/libmythtv/programinfo.h and is
107107
# the number of items in a ProgramInfo QStringList group used by

mythtv/bindings/python/MythTV/MythTV.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
}
4545

4646
BACKEND_SEP = '[]:[]'
47-
PROTO_VERSION = 44
47+
PROTO_VERSION = 45
4848
PROGRAM_FIELDS = 47
4949

5050
class MythTV:

mythtv/libs/libmythdb/mythversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* ProgramInfo network protocol layout in the following files:
1717
*
1818
* MythWeb
19-
* mythplugins/mythweb/includes/mythbackend.php (version number)
19+
* mythplugins/mythweb/classes/MythBackend.php (version number)
2020
* mythplugins/mythweb/modules/tv/includes/objects/Program.php (layout)
2121
*
2222
* MythTV Perl Bindings
@@ -27,7 +27,7 @@
2727
* mythtv/bindings/python/MythTV/MythTV.py (version number)
2828
* mythtv/bindings/python/MythTV/MythTV.py (layout)
2929
*/
30-
#define MYTH_PROTO_VERSION "44"
30+
#define MYTH_PROTO_VERSION "45"
3131

3232
#endif
3333

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
// mythtv
2+
#include "mythcontext.h"
3+
#include "mythdb.h"
4+
#include "channelgroup.h"
5+
6+
#define LOC QString("Channel Group: ")
7+
#define LOC_ERR QString("Channel Group, Error: ")
8+
9+
ChannelGroupItem& ChannelGroupItem::operator=(const ChannelGroupItem &other)
10+
{
11+
grpid = other.grpid;
12+
name = (other.name);
13+
14+
return *this;
15+
}
16+
17+
ChannelGroupItem::ChannelGroupItem(const ChannelGroupItem &other)
18+
{
19+
(*this) = other;
20+
}
21+
22+
inline bool lt_group(const ChannelGroupItem &a, const ChannelGroupItem &b)
23+
{
24+
return QString::localeAwareCompare(a.name, b.name) < 0;
25+
}
26+
27+
bool ChannelGroup::ToggleChannel(uint chanid, int changrpid, int delete_chan)
28+
{
29+
// Check if it already exists for that chanid...
30+
MSqlQuery query(MSqlQuery::InitCon());
31+
query.prepare(
32+
"SELECT channelgroup.id "
33+
"FROM channelgroup "
34+
"WHERE channelgroup.chanid = :CHANID AND "
35+
"channelgroup.grpid = :GRPID "
36+
"LIMIT 1");
37+
query.bindValue(":CHANID", chanid);
38+
query.bindValue(":GRPID", changrpid);
39+
40+
if (!query.exec() || !query.isActive())
41+
{
42+
MythDB::DBError("ChannelGroup::ToggleChannel", query);
43+
return false;
44+
}
45+
else if ((query.size() > 0) && delete_chan)
46+
{
47+
// We have a record...Remove it to toggle...
48+
query.next();
49+
QString id = query.value(0).toString();
50+
query.prepare(
51+
QString("DELETE FROM channelgroup "
52+
"WHERE id = '%1'").arg(id));
53+
query.exec();
54+
VERBOSE(VB_IMPORTANT, LOC + QString("Removing channel with id=%1.").arg(id));
55+
}
56+
else if (query.size() == 0)
57+
{
58+
// We have no record...Add one to toggle...
59+
query.prepare(
60+
QString("INSERT INTO channelgroup (chanid,grpid) "
61+
"VALUES ('%1','%2')").arg(chanid).arg(changrpid));
62+
query.exec();
63+
VERBOSE(VB_IMPORTANT, LOC + QString("Adding channel %1 to group %2.").arg(chanid).arg(changrpid));
64+
}
65+
66+
return true;
67+
}
68+
69+
bool ChannelGroup::AddChannel(uint chanid, int changrpid)
70+
{
71+
// Check if it already exists for that chanid...
72+
MSqlQuery query(MSqlQuery::InitCon());
73+
query.prepare(
74+
"SELECT channelgroup.id "
75+
"FROM channelgroup "
76+
"WHERE channelgroup.chanid = :CHANID AND "
77+
"channelgroup.grpid = :GRPID "
78+
"LIMIT 1");
79+
query.bindValue(":CHANID", chanid);
80+
query.bindValue(":GRPID", changrpid);
81+
82+
if (!query.exec() || !query.isActive())
83+
{
84+
MythDB::DBError("ChannelGroup::ToggleChannel", query);
85+
return false;
86+
}
87+
else if (query.size() == 0)
88+
{
89+
// We have no record...Add one to toggle...
90+
query.prepare(
91+
QString("INSERT INTO channelgroup (chanid,grpid) "
92+
"VALUES ('%1','%2')").arg(chanid).arg(changrpid));
93+
query.exec();
94+
VERBOSE(VB_IMPORTANT, LOC + QString("Adding channel %1 to group %2.").arg(chanid).arg(changrpid));
95+
}
96+
97+
return true;
98+
}
99+
100+
bool ChannelGroup::DeleteChannel(uint chanid, int changrpid)
101+
{
102+
// Check if it already exists for that chanid...
103+
MSqlQuery query(MSqlQuery::InitCon());
104+
query.prepare(
105+
"SELECT channelgroup.id "
106+
"FROM channelgroup "
107+
"WHERE channelgroup.chanid = :CHANID AND "
108+
"channelgroup.grpid = :GRPID "
109+
"LIMIT 1");
110+
query.bindValue(":CHANID", chanid);
111+
query.bindValue(":GRPID", changrpid);
112+
113+
if (!query.exec() || !query.isActive())
114+
{
115+
MythDB::DBError("ChannelGroup::ToggleChannel", query);
116+
return false;
117+
}
118+
else if (query.size() > 0)
119+
{
120+
// We have a record...Remove it to toggle...
121+
query.next();
122+
QString id = query.value(0).toString();
123+
query.prepare(
124+
QString("DELETE FROM channelgroup "
125+
"WHERE id = '%1'").arg(id));
126+
query.exec();
127+
VERBOSE(VB_IMPORTANT, LOC + QString("Removing channel with id=%1.").arg(id));
128+
}
129+
130+
return true;
131+
}
132+
133+
ChannelGroupList ChannelGroup::GetChannelGroups(void)
134+
{
135+
ChannelGroupList list;
136+
137+
MSqlQuery query(MSqlQuery::InitCon());
138+
139+
QString qstr = "SELECT grpid, name FROM channelgroupnames order by name";
140+
141+
query.prepare(qstr);
142+
143+
if (!query.exec() || !query.isActive())
144+
MythDB::DBError("ChannelGroup::GetChannelGroups", query);
145+
else
146+
{
147+
while (query.next())
148+
{
149+
ChannelGroupItem group(query.value(0).toUInt(),
150+
query.value(1).toString());
151+
list.push_back(group);
152+
}
153+
}
154+
155+
return list;
156+
}
157+
158+
// Cycle through the available groups, then all channels
159+
// Will cycle through to end then return -1
160+
// To signify all channels.
161+
int ChannelGroup::GetNextChannelGroup(const ChannelGroupList &sorted, int grpid)
162+
{
163+
// If no groups return -1 for all channels
164+
if (sorted.empty())
165+
return -1;
166+
167+
// If grpid is all channels (-1), then return the first grpid
168+
if (grpid == -1)
169+
return sorted[0].grpid;
170+
171+
ChannelGroupList::const_iterator it = find(sorted.begin(), sorted.end(), grpid);
172+
173+
// If grpid is not in the list, return -1 for all channels
174+
if (it == sorted.end())
175+
return -1;
176+
177+
++it;
178+
179+
// If we reached the end, the next option is all channels (-1)
180+
if (it == sorted.end())
181+
return -1;
182+
183+
return it->grpid;
184+
}
185+
186+
QString ChannelGroup::GetChannelGroupName(int grpid)
187+
{
188+
// All Channels
189+
if (grpid == -1)
190+
return QObject::tr("All Channels");
191+
192+
MSqlQuery query(MSqlQuery::InitCon());
193+
194+
QString qstr = QString("SELECT name FROM channelgroupnames where grpid='%1'")
195+
.arg(grpid);
196+
197+
query.prepare(qstr);
198+
199+
if (!query.exec() || !query.isActive())
200+
MythDB::DBError("ChannelGroup::GetChannelGroups", query);
201+
else if (query.size() > 0)
202+
{
203+
query.next();
204+
return query.value(0).toString();
205+
}
206+
207+
return "";
208+
}
209+
210+
int ChannelGroup::GetChannelGroupId(QString changroupname)
211+
{
212+
// All Channels
213+
if (changroupname == "All Channels")
214+
return -1;
215+
216+
MSqlQuery query(MSqlQuery::InitCon());
217+
218+
QString qstr = QString("SELECT grpid FROM channelgroupnames where name='%1'")
219+
.arg(changroupname);
220+
221+
query.prepare(qstr);
222+
223+
if (!query.exec() || !query.isActive())
224+
MythDB::DBError("ChannelGroup::GetChannelGroups", query);
225+
else if (query.size() > 0)
226+
{
227+
query.next();
228+
return query.value(0).toUInt();
229+
}
230+
231+
return 0;
232+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#ifndef CHANNELGROUP_H
2+
#define CHANNELGROUP_H
3+
4+
// c/c++
5+
#include <vector>
6+
7+
// qt
8+
#include <QString>
9+
10+
class ChannelGroupItem
11+
{
12+
public:
13+
ChannelGroupItem(const ChannelGroupItem&);
14+
ChannelGroupItem(const uint _grpid,
15+
const QString &_name) :
16+
grpid(_grpid), name(_name) {}
17+
18+
bool operator == (uint _grpid) const
19+
{ return grpid == _grpid; }
20+
21+
ChannelGroupItem& operator=(const ChannelGroupItem&);
22+
23+
public:
24+
uint grpid;
25+
QString name;
26+
};
27+
typedef vector<ChannelGroupItem> ChannelGroupList;
28+
29+
/** \class ChannelGroup
30+
*/
31+
class MPUBLIC ChannelGroup
32+
{
33+
public:
34+
// ChannelGroup
35+
static ChannelGroupList GetChannelGroups(void);
36+
static bool ToggleChannel(uint chanid, int changrpid, int delete_chan);
37+
static bool AddChannel(uint chanid, int changrpid);
38+
static bool DeleteChannel(uint chanid, int changrpid);
39+
static int GetNextChannelGroup(const ChannelGroupList &sorted, int grpid);
40+
static QString GetChannelGroupName(int grpid);
41+
static int GetChannelGroupId(QString changroupname);
42+
43+
private:
44+
45+
};
46+
47+
#endif

0 commit comments

Comments
 (0)