Statistics
| Branch: | Tag: | Revision:

dvbd / src / tunermanager.cpp @ 59be6a47

History | View | Annotate | Download (8.16 KB)

1
/*
2
  Copyright 2003 John Knottenbelt
3
  
4
  This program is free software; you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation; either version 2 of the License, or
7
  (at your option) any later version.
8
 
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
 
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17
*/
18

    
19
#include "config.h"
20
#include "dvbd.h"
21
#include "tunermanager.h"
22
#include "tuner.h"
23
#include "tuneparams.h"
24
#include "configfile.h"
25
#include "stringutil.h"
26
#include <iostream>
27
#include <cassert>
28
#include <set>
29
#include <vector>
30

    
31
TunerManager::~TunerManager()
32
{
33
  // Destroy the tuners
34
  for (TunerList::iterator i = tuners.begin(); i != tuners.end(); i++)
35
    delete *i;
36
}
37

    
38
void TunerManager::parseCommandLine(int argc, char *argv[])
39
{
40
  // Read in the type / tuner / channels triples
41
  for (int x = 0; x < argc; x+=3) 
42
    add(argv[x], argv[x+1], argv[x+2]);
43
}
44

    
45
bool TunerManager::parseConfig(ConfigFile &c)
46
{
47
  int numcards = toInt(c.get("numcards"));
48

    
49
  for (int i = 0; i < numcards; i++) {
50
    std::string card = c.get("card" + toString(i));
51
    std::vector<std::string> words;
52

    
53
    splitString(card, ':', words);
54
    if (words.size() != 3) {
55
      std::cerr << "Error parsing card definition. Expected 3 segments, got "
56
                << words.size() << "\n"
57
                << card 
58
                << std::endl;
59
      return false;
60
    }
61
    add(words[0], words[1], words[2]);
62
  }
63

    
64
  return true;
65
}
66

    
67
bool TunerManager::add( const std::string &type, 
68
                        const std::string &device, 
69
                        const std::string &channels )
70
{
71
  ChannelMap *cm = new ChannelMap;
72

    
73
  if (!readChannelsConf(type, channels, *cm)) {
74
    std::cerr << "Fatal error: failed to read " << channels << " file\n";
75
    return false;
76
  }
77
    
78
  Tuner *t = new Tuner(device);
79

    
80
  tuners.push_back(t);
81
  tunerChannelMap[t] = cm;
82
    
83
  TunerList *&typedTuners = typeTunerMap[type];
84
  if (typedTuners == NULL)
85
    typedTuners = new TunerList;
86

    
87
  typedTuners->push_back(t);  
88
  return true;
89
}
90

    
91
bool TunerManager::validType(const std::string &type) const
92
{
93
  return typeTunerMap.find(type) != typeTunerMap.end();
94
}
95

    
96
bool TunerManager::validChannel(const std::string &type, const std::string &channel) const
97
{
98
  TypeTunerMap::const_iterator li = typeTunerMap.find(type);
99
  if (li == typeTunerMap.end())
100
    return false;
101

    
102
  const TunerList &l = *li->second;
103

    
104
  for (TunerList::const_iterator i = l.begin(); i != l.end(); i++) {
105
    Tuner *t = *i;
106

    
107
    TunerChannelMap::const_iterator j = tunerChannelMap.find(t);
108
    assert(j != tunerChannelMap.end());
109

    
110
    ChannelMap *cm = j->second;
111

    
112
    ChannelMap::const_iterator k = cm->find(channel);
113
    if (k != cm->end())
114
      return true;
115
  }
116

    
117
  // No tuner found to tune this channel
118
  return false;
119
}
120

    
121
void TunerManager::getTunableChannels(const std::string &type, int priority, StringList &channels) const
122
{
123
  TypeTunerMap::const_iterator li = typeTunerMap.find(type);
124
  if (li == typeTunerMap.end())
125
    return;
126

    
127
  const TunerList &l = *li->second;
128
  std::set<std::string> history;
129

    
130
  for (TunerList::const_iterator i = l.begin(); i != l.end(); i++) {
131
    Tuner *t = *i;
132

    
133
    TunerChannelMap::const_iterator j = tunerChannelMap.find(t);
134
    assert(j != tunerChannelMap.end());
135

    
136
    ChannelMap *cm = j->second;
137

    
138
    for (ChannelMap::const_iterator k = cm->begin();
139
         k != cm->end(); k++) {
140
      const std::string &channel = k->first;
141

    
142
      if (history.find(channel) == history.end() &&
143
          canGetDemuxers(type, channel, priority)) {
144
        channels.push_back(channel);
145
        history.insert(channel);
146
      }
147
    }
148
  }
149
}
150

    
151
bool TunerManager::canGetDemuxers(const std::string &type, const std::string &channel,
152
                                  int priority) const
153
{
154
  // Without actually allocating a demuxer 
155
  // see if it is possible to tune the channel.
156

    
157
  TypeTunerMap::const_iterator li = typeTunerMap.find(type);
158
  assert(li != typeTunerMap.end());
159

    
160
  const TunerList &l = *li->second;
161

    
162
  for (TunerList::const_iterator i = l.begin(); i != l.end(); i++) {
163
    Tuner *t = *i;
164
    ChannelMap *cm = tunerChannelMap.find(t)->second;
165
    ChannelMap::iterator j = cm->find(channel);
166

    
167
    if (j != cm->end()) {
168
      const TuneParams *c = j->second;
169

    
170
      // Tuner with no subscribers
171
      if (t->getNumSubscribers() == 0)
172
        return true;
173

    
174
      if (!t->getTuneParams()->sameAsExceptPIDs(*c)) {
175
        // Tuner on a different frequency with subscribers all of
176
        // lesser priority
177
        if (t->getPriority() < priority)
178
          return true;
179
        else 
180
          continue;
181
      }
182

    
183
      Source *audio = t->getDemuxer(c->getAudioPID(), false, Demuxer::Audio);
184
      Source *video = t->getDemuxer(c->getVideoPID(), false, Demuxer::Video);
185

    
186
      // Check to see if perhaps someone else has already
187
      // tuned the audio or video channels (this should
188
      // not result in a new subscription to the tuner).
189
      int additionalRequired = 0;
190

    
191
      if (audio && audio->getNumSubscribers() == 0)
192
        additionalRequired++;
193

    
194
      if (video && video->getNumSubscribers() == 0)
195
        additionalRequired++;
196

    
197
      // Check if the tuner has the PIDS available
198
      // (ignoring subscriptions of lower priority)
199
      if (t->getNumSubscribers(priority) + additionalRequired < t->getMaxNumSubscribers()) 
200
        return true;
201
    }
202
  }
203

    
204
  return false;
205
}
206

    
207
void TunerManager::getDemuxers(const std::string &type, const std::string &channel,
208
                               bool convertToPS, SourceList &demuxers, int priority) 
209
{
210
  TypeTunerMap::iterator li = typeTunerMap.find(type);
211
  assert(li != typeTunerMap.end());
212

    
213
  const TunerList &l = *li->second;
214

    
215
  demuxers.clear();
216

    
217
  // Stratgey:
218
  // Try to allocate to a tuner already in use
219
  // Try to allocate to a free tuner
220

    
221
 tryAgain:
222
  for (TunerList::const_iterator i = l.begin(); i != l.end(); i++) {
223
    Tuner *t = *i;
224
    ChannelMap *cm = tunerChannelMap.find(t)->second;
225
    ChannelMap::iterator j = cm->find(channel);
226

    
227
    if (j != cm->end()) {
228
      const TuneParams *c = j->second;
229

    
230
      if (t->getNumSubscribers() == 0)
231
        t->setTuneParams(c);
232

    
233
      if (!t->getTuneParams()->sameAsExceptPIDs(*c)) 
234
        continue;
235

    
236
      Source *audio = t->getDemuxer(c->getAudioPID(), convertToPS, Demuxer::Audio);
237
      Source *video = t->getDemuxer(c->getVideoPID(), convertToPS, Demuxer::Video);
238

    
239
      // Check to see if perhaps someone else has already
240
      // tuned the audio or video channels (this should
241
      // not result in a new subscription to the tuner).
242
      int additionalRequired = 0;
243

    
244
      if (audio && audio->getNumSubscribers() == 0)
245
        additionalRequired++;
246

    
247
      if (video && video->getNumSubscribers() == 0)
248
        additionalRequired++;
249

    
250
      // Check if the tuner has the PIDS available
251
      if (t->getNumSubscribers() + additionalRequired >= t->getMaxNumSubscribers()) 
252
        continue;
253

    
254
      if (audio) 
255
        demuxers.push_back(audio);
256

    
257
      if (video)
258
        demuxers.push_back(video);
259

    
260
      return;
261
    }
262
  }
263

    
264
  // Try to free up a tuner/demuxers based on priority
265
  for (TunerList::const_iterator i = l.begin(); i != l.end(); i++) {
266
    Tuner *t = *i;
267
    ChannelMap *cm = tunerChannelMap.find(t)->second;
268
    ChannelMap::iterator j = cm->find(channel);
269

    
270
    if (j != cm->end()) {
271
      const TuneParams *c = j->second;
272

    
273
      if (t->getTuneParams()->sameAsExceptPIDs(*c)) {
274
        // We need to kick off a demuxer, if possible
275
        if (t->Source::unsubscribe(priority) > 0)
276
          goto tryAgain;
277
      }
278
      else {
279
        // We need to kick off all subscribers,
280
        // if possible
281
        if (priority > t->getPriority()) {
282
          t->unsubscribeAll();
283
          goto tryAgain;
284
        }
285
      }
286
    }
287
  }
288

    
289
  // We failed :(
290
}
291

    
292
void TunerManager::addSelectFDs(Select &s) const
293
{
294
  for (TunerList::const_iterator i = tuners.begin(); i != tuners.end(); i++)
295
    (*i)->addSelectFDs(s);
296
}
297

    
298
bool TunerManager::isReady(const Select &s) const
299
{
300
  for (TunerList::const_iterator i = tuners.begin(); i != tuners.end(); i++)
301
    if ((*i)->isReady(s))
302
      return true;
303
  return false;
304
}
305

    
306
void TunerManager::processReady(const Select &s)
307
{
308
  for (TunerList::iterator i = tuners.begin(); i != tuners.end(); i++)
309
    if ((*i)->isReady(s))
310
      (*i)->process();
311
}
312