Statistics
| Branch: | Tag: | Revision:

dvbd / src / dvbcat.cpp @ 900cea42

History | View | Annotate | Download (5.32 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 "utils.h"
22
#include "stringutil.h"
23
#include "select.h"
24
#include "clientconnection.h"
25
#include "unixclientsocket.h"
26

    
27
#include <string>
28
#include <iostream>
29
#include <time.h>
30
#include <getopt.h>
31
#include <cerrno>
32
#include <fstream>
33
#include <fcntl.h>
34

    
35
void usage(const char *progname);
36
time_t convertTime(const char *theTime);
37
int openOutputFile(std::string &outputfile);
38
void closeOutputFile(int fd);
39

    
40
int main(int argc, char *argv[])
41
{
42
  // improve iostream performance
43
  std::ios::sync_with_stdio(false);
44

    
45
  std::string outputFile = "-";
46
  std::string socketFile = DEFAULT_SOCKET_FILE;
47
  bool durationSpecified = false;
48
  unsigned duration = 0;
49
  int priority = 10;
50
  bool convertToPS = false;
51

    
52
  while (true) {
53
    static struct option long_options[] = {
54
      {"duration", 1, 0, 'd'},
55
      {"priority", 1, 0, 'p'},
56
      {"output", 1, 0, 'o'},
57
      {"socket", 1, 0, 's'},
58
      {"ps", 0, 0, 'P'},
59
      {0, 0, 0, 0}
60
    };
61
 
62
    int option_index = 0;
63
    int c = getopt_long(argc, argv, "Pd:p:o:s:", long_options, &option_index);
64
    if (c == -1)
65
      break;
66
    switch (c) {
67
    case 'd':
68
      durationSpecified = true;
69
      duration = toInt(optarg);
70
      break;
71
    case 'p':
72
      priority = toInt(optarg);
73
      break;
74
    case 'o':
75
      outputFile = optarg;
76
      break;
77
    case 's':
78
      socketFile = optarg;
79
      break;
80
    case 'P':
81
      convertToPS = true;
82
      break;
83
    default:
84
      usage(argv[0]);
85
      return 1;
86
    }
87
  }
88

    
89
  if (argc - optind != 2) {
90
    if (argc - optind != 0)
91
      std::cerr << "Incorrect number of arguments passed (expected 2, got " 
92
                << argc - optind << ")\n\n";
93

    
94
    usage(argv[0]);
95
    return 1;
96
  }
97

    
98
  // Parse the command line arguments
99
  std::string type(argv[optind++]);
100
  std::string channel(argv[optind++]);
101

    
102
  ClientConnection client(socketFile);
103
  if (!client) {
104
    std::cerr << "Fatal error: failed to connect to server on socket " << socketFile << std::endl;
105
    return 1;
106
  }
107

    
108
  // Open the output file
109
  int outputFd = openOutputFile(outputFile);
110
  if (outputFd < 0) {
111
    std::cerr << "Fatal error: failed to open " << outputFile << " for output"
112
              << std::endl;
113
    return 1;
114
  }
115

    
116
  // Tune the channel
117
  if (!client.tune(type, channel, convertToPS, priority)) {
118
    std::cerr << "Failed to tune channel. Response from server was:\n"
119
              << client.getError() << "\n";
120
    return 1;
121
  }
122

    
123
  UnixClientSocket &control = client.control();
124
  UnixClientSocket &data = client.data();
125

    
126
  control.setBlocking(false);
127
  data.setBlocking(false);
128

    
129
  time_t start = time(NULL);
130
  Select s;
131
  do {
132
    s.clearFDs();
133
    control.addSelectFDs(s);
134
    data.addSelectFDs(s);
135

    
136
    if (durationSpecified) {
137
      unsigned elapsed = time(NULL) - start;
138
      if (elapsed >= duration*60) {
139
        std::cerr << "Duration elapsed" << std::endl;
140
        break;
141
      }
142
      s.addAlarm(duration * 60 - elapsed, 0);
143
    }
144

    
145
    s.wait();
146

    
147
    if (data.isReady(s)) {
148
      if (!data.processReady(s)) {
149
        std::cerr << "Server closed data connection" << std::endl;
150
        break;
151
      }
152

    
153
      char buffer[1024];
154
      int bytesRead = data.read(buffer, 1024);
155

    
156
      if (bytesRead > 0) 
157
        write(outputFd, buffer, bytesRead);
158
    }
159
    else if (control.isReady(s)) {
160
      if (!control.processReady(s)) {
161
        std::cerr << "Server closed control connection" << std::endl;
162
        break;
163
      }
164

    
165
      std::string line;
166
      if (control.readLine(line)) 
167
        std::cerr << line;
168
    }
169
  } while (true);
170

    
171
  closeOutputFile(outputFd);
172
  return 0;
173
}
174

    
175
int openOutputFile(std::string &outputFile)
176
{
177
  if (outputFile == "-") 
178
    return 0;
179

    
180
  int openMode = O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE;
181

    
182
  // Don't bother caching if possible
183
#ifdef O_STREAMING
184
  openMode |= O_STREAMING;
185
#endif
186
  
187
  return open(outputFile.c_str(), openMode, 0644);
188
}
189

    
190
void closeOutputFile(int fd)
191
{
192
  if (fd > 0)
193
    close(fd);
194
}
195

    
196
void usage(const char *progname) {
197
  std::cerr << "Usage: " << progname << " [OPTION] TYPE CHANNEL\n"
198
            << "Receive DVB broadcast for channel CHANNEL, using DVB-card\n"
199
            << "\n"
200
            << "TYPE can be dvb-t, dvb-s or dvb-c.\n"
201
            << "\n"
202
            << "  -d, --duration         Time to stream for in minutes.\n"
203
            << "  -p, --priority         Priority of stream (default is 10\n"
204
            << "                         higher priorities may dislodge lower\n"
205
            << "                         ones).\n"
206
            << "  -o, --output           Record to output file\n"
207
            << "                         (default is standard output).\n"
208
            << "  -s, --socket           Specify socket to connect to\n"
209
            << "                         (default is " << DEFAULT_SOCKET_FILE << ")\n"
210
            << "  -P, --ps               Convert stream to program stream\n";
211
}