Statistics
| Branch: | Tag: | Revision:

dvbd / src / tuner.cpp @ 2cecea08

History | View | Annotate | Download (4.83 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 "tuner.h"
21
#include "demuxer.h"
22
#include "tuneparams.h"
23
#include "debug.h"
24

    
25
#include <iostream>
26
#include <cstdlib>
27
#include <cerrno>
28
#include <cstring>
29
#include <cassert>
30
#include <sys/types.h>
31
#include <sys/stat.h>
32
#include <fcntl.h>
33

    
34
// Size of a TS packet
35
#define TS_SIZE 188
36

    
37
Tuner::Tuner( const std::string &frontendDevice )
38
    : numReaders(0),
39
      frontendFD(-1),
40
      dvrFD(-1),
41
      tuneParams(NULL),
42
      frontendDevice(frontendDevice)      
43
{
44
  // Derive the demuxDevice from the frontend string
45
  unsigned fPos = frontendDevice.find("frontend");
46
  if (fPos == std::string::npos) {
47
    std::cerr << "Fatal error: frontendDevice not in expected form\n";
48
    exit(1);
49
  }
50

    
51
  demuxDevice = frontendDevice;
52
  demuxDevice.replace(fPos, 8, "demux" );
53

    
54
  dvrDevice = frontendDevice;
55
  dvrDevice.replace(fPos, 8, "dvr" );
56
  
57
  if (debugging) {
58
    // Debugging information
59
    std::cerr << "frontend: " << frontendDevice << "\n"
60
              << "demux: " << demuxDevice << "\n"
61
              << "dvr: " << dvrDevice << std::endl;
62
  }
63
}
64

    
65
Tuner::~Tuner()
66
{
67
  List copy = subscribers;
68

    
69
  unsubscribeAll();
70

    
71
  // Destroy all the Demuxes
72
  for (int h = 0; h < 2; h++) {
73
    DemuxerMap &dm = demuxerMap[h];
74
    for (DemuxerMap::iterator i = dm.begin(); i != dm.end(); i++) {
75
      PIDMap &pidmap = i->second;
76
      for (PIDMap::iterator j = pidmap.begin(); j != pidmap.end(); j++)
77
        delete j->second;
78
    }
79
  }
80
}
81

    
82
void Tuner::setTuneParams(const TuneParams *tuneParams)
83
{
84
  if (numReaders > 0) {
85
    std::cerr << "Fatal error: can't change tuning parameters while readers > 0\n";
86
    exit(1);
87
  }
88
  this->tuneParams = tuneParams;
89
}
90

    
91
void Tuner::addSelectFDs(Select &s) const
92
{
93
  if (dvrFD != -1)
94
    s.addReadFD(dvrFD);
95
}
96

    
97
bool Tuner::isReady(const Select &s) const {
98
  if (dvrFD == -1)
99
    return false;
100

    
101
  return s.readyToRead(dvrFD);
102
}
103

    
104
Demuxer *Tuner::makeNewDemuxer(int pid, bool convertToPS, Demuxer::PESType pesType) const
105
{
106
  return new Demuxer(const_cast<Tuner *>(this), pid, convertToPS, pesType);
107
}
108

    
109
// Keep a list of all the demuxers ever created
110
Demuxer *Tuner::getDemuxer(int pid, bool convertToPS, Demuxer::PESType pesType) const
111
{
112
  // Strictly speaking getDemuxer() is not a const
113
  // method, however, it does have minimal side
114
  // effects since creating a Demuxer is not
115
  // the same thing as subscribing to one.
116

    
117
  if (pid == 0)
118
    return NULL;
119

    
120
  assert(tuneParams != NULL);
121

    
122
  DemuxerMap &dm = demuxerMap[ convertToPS ? 1 : 0 ];
123
  PIDMap &pidMap = dm[tuneParams];
124
  Demuxer *&demuxer = pidMap[pid];
125

    
126
  if (demuxer == NULL)
127
    demuxer = makeNewDemuxer(pid, convertToPS, pesType);
128

    
129
  return demuxer;
130
}
131

    
132
bool Tuner::openFrontend()
133
{
134
  if((frontendFD = open(frontendDevice.c_str(),O_RDWR)) < 0){
135
    std::cerr << "Error opening frontend device " << frontendDevice << ":" 
136
              << strerror(errno) << std::endl;
137
    return false;
138
  }
139
  else 
140
    return true;
141
}
142

    
143
void Tuner::closeFrontend()
144
{
145
  if (frontendFD >= 0) {
146
    close(frontendFD);
147
    frontendFD = -1;
148
  }
149
}
150

    
151
bool Tuner::openDvr()
152
{
153
  if((dvrFD = open(dvrDevice.c_str(),O_RDONLY|O_NONBLOCK)) < 0){
154
    std::cerr << "Error opening DVR device " << dvrDevice << ":" 
155
              << strerror(errno) << std::endl;
156
    return false;
157
  }
158
  return true;
159
}
160

    
161
void Tuner::closeDvr()
162
{
163
  if (dvrFD >= 0) {
164
    close(dvrFD);
165
    dvrFD = -1;
166
  }
167
}
168

    
169
bool Tuner::tune()
170
{
171
  return tuneParams->tune(frontendFD);
172
}
173

    
174
bool Tuner::subscribe(Sink *s)
175
{
176
  // On the first subscriber make sure to tune the channel
177
  // and open the dvr device 
178

    
179
  if (getNumSubscribers() == 0) {
180
    assert(tuneParams);
181
    
182
    if (!openFrontend())
183
      return false;
184

    
185
    if (!tune()) {
186
      closeFrontend();
187
      return false;
188
    }
189

    
190
    if (!openDvr()) {
191
      closeFrontend();
192
      return false;
193
    }
194

    
195
  }
196
  return Source::subscribe(s);
197
}
198

    
199
void Tuner::unsubscribe(Sink *s)
200
{
201
  Source::unsubscribe(s);
202

    
203
  // On the last subscriber close down the dvr channel
204
  if (getNumSubscribers() == 0) {
205
    closeDvr();
206
    closeFrontend();
207
  }
208
}
209

    
210
void Tuner::process() {
211
  if (dvrFD == -1) 
212
    return;
213

    
214
  unsigned char data[TS_SIZE];
215
  int  bytesread;
216

    
217
  if ((bytesread = read(dvrFD, (char *) data, TS_SIZE)) > 0) 
218
    sendData(data, (unsigned) bytesread);
219
}