Statistics
| Branch: | Tag: | Revision:

dvbd / tuner.cpp @ bfdb7446

History | View | Annotate | Download (4.67 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 (DemuxerMap::iterator i = demuxerMap.begin(); i != demuxerMap.end(); i++) {
73
    PIDMap &pidmap = i->second;
74
    for (PIDMap::iterator j = pidmap.begin(); j != pidmap.end(); j++)
75
      delete j->second;
76
  }
77
}
78

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

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

    
94
bool Tuner::isReady(const Select &s) const {
95
  if (dvrFD == -1)
96
    return false;
97

    
98
  return s.readyToRead(dvrFD);
99
}
100

    
101
Demuxer *Tuner::makeNewDemuxer(int pid, Demuxer::PESType pesType) const
102
{
103
  return new Demuxer(const_cast<Tuner *>(this), pid, pesType);
104
}
105

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

    
114
  if (pid == 0)
115
    return NULL;
116

    
117
  assert(tuneParams != NULL);
118

    
119
  PIDMap &pidMap = demuxerMap[tuneParams];
120
  Demuxer *&demuxer = pidMap[pid];
121

    
122
  if (demuxer == NULL)
123
    demuxer = makeNewDemuxer(pid, pesType);
124

    
125
  return demuxer;
126
}
127

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

    
139
void Tuner::closeFrontend()
140
{
141
  if (frontendFD >= 0) {
142
    close(frontendFD);
143
    frontendFD = -1;
144
  }
145
}
146

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

    
157
void Tuner::closeDvr()
158
{
159
  if (dvrFD >= 0) {
160
    close(dvrFD);
161
    dvrFD = -1;
162
  }
163
}
164

    
165
bool Tuner::tune()
166
{
167
  return tuneParams->tune(frontendFD);
168
}
169

    
170
bool Tuner::subscribe(Sink *s)
171
{
172
  // On the first subscriber make sure to tune the channel
173
  // and open the dvr device 
174

    
175
  if (getNumSubscribers() == 0) {
176
    assert(tuneParams);
177
    
178
    if (!openFrontend())
179
      return false;
180

    
181
    if (!tune()) {
182
      closeFrontend();
183
      return false;
184
    }
185

    
186
    if (!openDvr()) {
187
      closeFrontend();
188
      return false;
189
    }
190

    
191
  }
192
  return Source::subscribe(s);
193
}
194

    
195
void Tuner::unsubscribe(Sink *s)
196
{
197
  Source::unsubscribe(s);
198

    
199
  // On the last subscriber close down the dvr channel
200
  if (getNumSubscribers() == 0) {
201
    closeDvr();
202
    closeFrontend();
203
  }
204
}
205

    
206
void Tuner::process() {
207
  if (dvrFD == -1) 
208
    return;
209

    
210
  unsigned char data[TS_SIZE];
211
  int  bytesread;
212

    
213
  if ((bytesread = read(dvrFD, (char *) data, TS_SIZE)) > 0) 
214
    sendData(data, (unsigned) bytesread);
215
}