~ubuntu-branches/ubuntu/jaunty/ecasound2.2/jaunty

« back to all changes in this revision

Viewing changes to libecasound/audioio-ogg.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Junichi Uekawa
  • Date: 2005-04-14 09:15:48 UTC
  • Revision ID: james.westby@ubuntu.com-20050414091548-o7kgb47z0tcunh0s
Tags: upstream-2.4.1
ImportĀ upstreamĀ versionĀ 2.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ------------------------------------------------------------------------
 
2
// audioio-ogg.cpp: Interface for ogg vorbis decoders and encoders.
 
3
// Copyright (C) 2000-2002,2004-2005 Kai Vehmanen
 
4
//
 
5
// This program is free software; you can redistribute it and/or modify
 
6
// it under the terms of the GNU General Public License as published by
 
7
// the Free Software Foundation; either version 2 of the License, or
 
8
// (at your option) any later version.
 
9
// 
 
10
// This program is distributed in the hope that it will be useful,
 
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
// GNU General Public License for more details.
 
14
// 
 
15
// You should have received a copy of the GNU General Public License
 
16
// along with this program; if not, write to the Free Software
 
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 
18
// ------------------------------------------------------------------------
 
19
 
 
20
#include <string>
 
21
#include <cstdlib> /* atol() */
 
22
#include <unistd.h> /* stat() */
 
23
#include <sys/stat.h> /* stat() */
 
24
 
 
25
#include <kvu_message_item.h>
 
26
#include <kvu_numtostr.h>
 
27
 
 
28
#include "audioio-ogg.h"
 
29
 
 
30
#include "eca-logger.h"
 
31
 
 
32
string OGG_VORBIS_INTERFACE::default_input_cmd = "ogg123 -d raw -o byteorder:%E --file=- %f";
 
33
string OGG_VORBIS_INTERFACE::default_output_cmd = "oggenc -b %B --raw --raw-bits=%b --raw-chan=%c --raw-rate=%s --raw-endianness 0 --output=%f -";
 
34
long int OGG_VORBIS_INTERFACE::default_output_default_bitrate = 128000;
 
35
 
 
36
void OGG_VORBIS_INTERFACE::set_input_cmd(const std::string& value) { OGG_VORBIS_INTERFACE::default_input_cmd = value; }
 
37
void OGG_VORBIS_INTERFACE::set_output_cmd(const std::string& value) { OGG_VORBIS_INTERFACE::default_output_cmd = value; }
 
38
 
 
39
OGG_VORBIS_INTERFACE::OGG_VORBIS_INTERFACE(const std::string& name)
 
40
{
 
41
  set_label(name);
 
42
  finished_rep = false;
 
43
  bitrate_rep = OGG_VORBIS_INTERFACE::default_output_default_bitrate;
 
44
}
 
45
 
 
46
OGG_VORBIS_INTERFACE::~OGG_VORBIS_INTERFACE(void)
 
47
{
 
48
  if (is_open() == true) {
 
49
    close();
 
50
  }
 
51
}
 
52
 
 
53
void OGG_VORBIS_INTERFACE::open(void) throw (AUDIO_IO::SETUP_ERROR &)
 
54
{
 
55
  std::string urlprefix;
 
56
  triggered_rep = false;
 
57
 
 
58
  if (io_mode() == io_read) {
 
59
    struct stat buf;
 
60
    int ret = ::stat(label().c_str(), &buf);
 
61
    if (ret != 0) {
 
62
      size_t offset = label().find_first_of("://");
 
63
      if (offset == std::string::npos) {
 
64
        throw(SETUP_ERROR(SETUP_ERROR::io_mode, "AUDIOIO-OGG: Can't open file " + label() + "."));
 
65
      }
 
66
      else {
 
67
        urlprefix = std::string(label(), 0, offset);
 
68
        ECA_LOG_MSG(ECA_LOGGER::user_objects, "(audioio-ogg) Found url; protocol '" + urlprefix + "'.");
 
69
      }
 
70
    }
 
71
 
 
72
    /* decoder supports: nothing configurable nor fixed
 
73
     * 
 
74
     * FIXME: we have no idea about the audio format of the 
 
75
     *        stream we get from the decoder... ybe we should force the decoder
 
76
     *        to generate RIFF wave to a named pipe and parse the header...? 
 
77
     */
 
78
  }
 
79
  else {
 
80
    /* encoder supports: coding, channel-count and srate configurable,
 
81
     *                   fixed to little endian */
 
82
    ECA_AUDIO_FORMAT::set_sample_endianess(ECA_AUDIO_FORMAT::se_little);
 
83
  }
 
84
 
 
85
  AUDIO_IO::open();
 
86
}
 
87
 
 
88
void OGG_VORBIS_INTERFACE::close(void)
 
89
{
 
90
  if (pid_of_child() > 0) {
 
91
      ECA_LOG_MSG(ECA_LOGGER::user_objects, "(audioio-mp3) Cleaning child process." + kvu_numtostr(pid_of_child()) + ".");
 
92
      clean_child();
 
93
      triggered_rep = false;
 
94
  }
 
95
 
 
96
  AUDIO_IO::close();
 
97
}
 
98
 
 
99
long int OGG_VORBIS_INTERFACE::read_samples(void* target_buffer, long int samples)
 
100
{
 
101
  if (triggered_rep != true) { 
 
102
    triggered_rep = true;
 
103
    fork_input_process();
 
104
  }
 
105
 
 
106
  if (f1_rep != 0) {
 
107
    bytes_rep = std::fread(target_buffer, 1, frame_size() * samples, f1_rep);
 
108
  }
 
109
  else {
 
110
    bytes_rep = 0;
 
111
  }
 
112
 
 
113
  if (bytes_rep < samples * frame_size() || bytes_rep == 0) {
 
114
    if (position_in_samples() == 0) 
 
115
      ECA_LOG_MSG(ECA_LOGGER::info, "(audioio-ogg) Can't start process \"" + fork_command() + "\". Please check your ~/.ecasound/ecasoundrc.");
 
116
    finished_rep = true;
 
117
    triggered_rep = false;
 
118
  }
 
119
  else 
 
120
    finished_rep = false;
 
121
 
 
122
  return(bytes_rep / frame_size());
 
123
}
 
124
 
 
125
void OGG_VORBIS_INTERFACE::write_samples(void* target_buffer, long int samples)
 
126
{
 
127
  if (triggered_rep != true) {
 
128
    triggered_rep = true;
 
129
    fork_output_process();
 
130
  }
 
131
 
 
132
  if (wait_for_child() != true) {
 
133
    finished_rep = true;
 
134
    triggered_rep = false;
 
135
  }
 
136
  else {
 
137
    if (filedes_rep > 0) {
 
138
      bytes_rep = ::write(filedes_rep, target_buffer, frame_size() * samples);
 
139
    }
 
140
    else {
 
141
      bytes_rep = 0;
 
142
    }
 
143
    if (bytes_rep < frame_size() * samples || bytes_rep == 0) {
 
144
      finished_rep = true;
 
145
      triggered_rep = false;
 
146
    }
 
147
    else finished_rep = false;
 
148
  }
 
149
}
 
150
 
 
151
void OGG_VORBIS_INTERFACE::seek_position(void) {
 
152
  if (pid_of_child() > 0) {
 
153
    ECA_LOG_MSG(ECA_LOGGER::user_objects, "(audioio-ogg) Cleaning child process." + kvu_numtostr(pid_of_child()) + ".");
 
154
    clean_child();
 
155
    triggered_rep = false;
 
156
  }
 
157
  set_position_in_samples(0);
 
158
}
 
159
 
 
160
void OGG_VORBIS_INTERFACE::set_parameter(int param, string value)
 
161
{
 
162
  switch (param) {
 
163
  case 1: 
 
164
    set_label(value);
 
165
    break;
 
166
 
 
167
  case 2: 
 
168
    long int numvalue = atol(value.c_str());
 
169
    if (numvalue > 0) 
 
170
      bitrate_rep = numvalue;
 
171
    else
 
172
      bitrate_rep = OGG_VORBIS_INTERFACE::default_output_default_bitrate;
 
173
    break;
 
174
  }
 
175
}
 
176
 
 
177
string OGG_VORBIS_INTERFACE::get_parameter(int param) const
 
178
{
 
179
  switch (param) {
 
180
  case 1: 
 
181
    return(label());
 
182
 
 
183
  case 2: 
 
184
    return(kvu_numtostr(bitrate_rep));
 
185
  }
 
186
  return("");
 
187
}
 
188
 
 
189
void OGG_VORBIS_INTERFACE::fork_input_process(void)
 
190
{
 
191
  string command = OGG_VORBIS_INTERFACE::default_input_cmd;
 
192
 
 
193
  // replace with 'little/big' byteorder
 
194
  if (command.find("%E") != string::npos) {
 
195
    string byteorder ("big");
 
196
    if (sample_endianess() == ECA_AUDIO_FORMAT::se_little) byteorder = "little";
 
197
    command.replace(command.find("%E"), 2, byteorder);
 
198
  }
 
199
 
 
200
  set_fork_command(command);
 
201
  set_fork_file_name(label());
 
202
  set_fork_pipe_name();
 
203
  fork_child_for_read();
 
204
  if (child_fork_succeeded() == true) {
 
205
    /* NOTE: the file description will be closed by 
 
206
     *       AUDIO_IO_FORKED_STREAM::clean_child() */
 
207
    filedes_rep = file_descriptor();
 
208
    f1_rep = fdopen(filedes_rep, "r"); /* not part of <cstdio> */
 
209
    if (f1_rep == 0) {
 
210
      finished_rep = true;
 
211
      triggered_rep = false;
 
212
    }
 
213
  }
 
214
  else
 
215
    f1_rep = 0;
 
216
}
 
217
 
 
218
void OGG_VORBIS_INTERFACE::fork_output_process(void)
 
219
{
 
220
  ECA_LOG_MSG(ECA_LOGGER::info, "(audioio-ogg) Starting to encode " + label() + " with vorbize.");
 
221
  string command = OGG_VORBIS_INTERFACE::default_output_cmd;
 
222
 
 
223
  // replace with bitrate
 
224
  if (command.find("%B") != string::npos) {
 
225
    command.replace(command.find("%B"), 2, kvu_numtostr((long int)(bitrate_rep / 1000)));
 
226
  }
 
227
 
 
228
  set_fork_command(command);
 
229
  set_fork_file_name(label());
 
230
 
 
231
  set_fork_bits(bits());
 
232
  set_fork_channels(channels());
 
233
  set_fork_sample_rate(samples_per_second());
 
234
 
 
235
  fork_child_for_write();
 
236
  if (child_fork_succeeded() == true) {
 
237
    filedes_rep = file_descriptor();
 
238
  }
 
239
  else {
 
240
    filedes_rep = 0;
 
241
  }
 
242
}