Beispiel #1
0
void PulseOutput::close() {
#ifdef DEBUG
  context->getReactor().debug();
#endif

  if (stream) {
    GM_DEBUG_PRINT("[pulse] disconnecting stream\n");
    pa_stream_disconnect(stream);
    pa_stream_unref(stream);
    stream=nullptr;
    }

  if (pulse_context) {
    GM_DEBUG_PRINT("[pulse] disconnecting context\n");
    pa_context_disconnect(pulse_context);
    pa_context_unref(pulse_context);
    pulse_context=nullptr;
    }
#ifdef DEBUG
  context->getReactor().debug();
#endif

  delete pa_io_event::recycle;
  delete pa_time_event::recycle;
  delete pa_defer_event::recycle;
  pa_io_event::recycle    = nullptr;
  pa_time_event::recycle  = nullptr;
  pa_defer_event::recycle = nullptr;
  pulsevolume             = PA_VOLUME_MUTED;
  af.reset();
  }
Beispiel #2
0
FXbool MMSInput::open(const FXString & uri) {
  mms=mms_connect(NULL,NULL,uri.text(),128*1024);
  if (!mms) {
    GM_DEBUG_PRINT("failed to connect\n");
    return false;
    }
  GM_DEBUG_PRINT("mms connected\n");
  return true;
  }
Beispiel #3
0
DBusHandlerResult dbus_status_item_filter(DBusConnection *connection,DBusMessage * msg,void */* data*/){
//  DEBUG_DBUS_MESSAGE(msg);
  DBusMessage *   reply;
  DBusMessageIter iter;
  DBusMessageIter dict;
  //DBusMessageIter dictentry;

  FXuint serial;
  if (dbus_message_has_path(msg,APPLICATION_STATUS_ITEM_PATH)){
    DEBUG_DBUS_MESSAGE(msg);
    if (dbus_message_has_interface(msg,APPLICATION_STATUS_ITEM_INTERFACE)) {
      if (dbus_message_is_method_call(msg,APPLICATION_STATUS_ITEM_INTERFACE,"Activate")){
        GMPlayerManager::instance()->cmd_toggle_shown();
        return gm_dbus_reply_if_needed(connection,msg);
        }
      else if (dbus_message_is_method_call(msg,APPLICATION_STATUS_ITEM_INTERFACE,"Scroll")){
        FXint delta;
        const FXchar * orientation;
        if (dbus_message_get_args(msg,NULL,DBUS_TYPE_INT32,&delta,DBUS_TYPE_STRING,&orientation,DBUS_TYPE_INVALID)) {

          //FIXME
          FXint level = GMPlayerManager::instance()->volume();
          level+=(delta/120);
          GMPlayerManager::instance()->volume(level);
          }
        return gm_dbus_reply_if_needed(connection,msg);
        }
      }
    else if (dbus_message_has_interface(msg,DBUS_INTERFACE_INTROSPECTABLE)) {
      if (dbus_message_is_method_call(msg,DBUS_INTERFACE_INTROSPECTABLE,"Introspect")){
        return gm_dbus_reply_string(connection,msg,appstatus_xml);
        }
      }
    else if (dbus_message_has_interface(msg,DBUS_INTERFACE_PROPERTIES)) {
      if (dbus_message_is_method_call(msg,DBUS_INTERFACE_PROPERTIES,"Get")){
        GM_DEBUG_PRINT("get\n");
        }
      else if (dbus_message_is_method_call(msg,DBUS_INTERFACE_PROPERTIES,"GetAll")){
        if ((reply=dbus_message_new_method_return(msg))!=NULL) {
          dbus_message_iter_init_append(reply,&iter);
          dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,"{sv}",&dict);
            gm_dbus_dict_append_path(&dict,"Menu",APPLICATION_STATUS_ITEM_MENU_PATH);
            gm_dbus_dict_append_string(&dict,"Category","ApplicationStatus");
            gm_dbus_dict_append_string(&dict,"Id","gogglesmm");
            gm_dbus_dict_append_string(&dict,"IconName","gogglesmm");
            gm_dbus_dict_append_string(&dict,"Status","Active");
            gm_dbus_dict_append_uint32(&dict,"WindowId",GMPlayerManager::instance()->getMainWindowId());
            gm_add_tooltip(&dict);
          dbus_message_iter_close_container(&iter,&dict);
          dbus_connection_send(connection,reply,&serial);
          dbus_message_unref(reply);
          }
        return DBUS_HANDLER_RESULT_HANDLED;
        }
      else if (dbus_message_is_method_call(msg,DBUS_INTERFACE_PROPERTIES,"Set")){
        }
      }
    }
  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  }
Beispiel #4
0
ID3V2::ID3V2(FXuchar *b,FXint len) : buffer(b),size(len),p(0),padstart(0),padend(0),length(-1) {
  const FXchar & flags = buffer[5];

  version = buffer[3];
  GM_DEBUG_PRINT("[id3v2] version %d\n",version);

  buffer+=10;
  size-=10;

  /// we can skip the footer
  if (version>=4 && flags&HAS_FOOTER)
    size-=10;

  /// Apply unsync, according to spec 2.3, the extended header also needs unsyncing
  if (flags&HAS_UNSYNC) {
    unsync(buffer,size);
    }

  /// skip the extended header
  if (version>=3 && flags&HAS_EXTENDED_HEADER) {
    FXint header_size;
    if (version==3)
      header_size = ID3_INT32(buffer);
    else
      header_size = ID3_SYNCSAFE_INT32(buffer);
    buffer+=header_size;
    }

  /// Parse
  p=0;
  while(p<size)
    parse_frame();
  }
void InputThread::ctrl_eos() {
  GM_DEBUG_PRINT("[input] end of stream reached\n");
  if (state!=StateProcessing) {
    //ctrl_flush(true);
    ctrl_close_input(true);
    }
  }
Beispiel #6
0
void ID3V2::parse_comment_frame(FXint framesize) {
  FXString key,field;

  const FXuchar & encoding = buffer[p];
  const FXchar* textstart  = (const FXchar*)(buffer+p+4);
  const FXint   textlength = framesize - 4;

  if (encoding==UTF16_BOM || encoding==UTF16) {
    FXint ksize = strwlen(textstart,textlength);
    FXint vsize = strwlen(textstart+ksize+2,textlength-ksize-2);
    parse_text(encoding,textstart,ksize,key);
    parse_text(encoding,textstart+ksize+2,vsize,field);
    }
  else {
    FXint ksize = strnlen(textstart,textlength);
    FXint vsize = strnlen(textstart+ksize+1,textlength-ksize-1);
    parse_text(encoding,textstart,ksize,key);
    parse_text(encoding,textstart+ksize+1,vsize,field);
    }

  FXString comment = key + " " + field;
  if (comment.find("iTunSMPB")>=0) {
    comment.simplify().scan("iTunSMPB %*x %hx %hx %lx",&padstart,&padend,&length);
    GM_DEBUG_PRINT("[id3v2] found iTunSMPB (padding %d %d, length %ld)\n",padstart,padend,length);
    }
  }
void InputThread::ctrl_open_inputs(const FXStringList & urls){
  for (FXint i=0;i<urls.no();i++){
    GM_DEBUG_PRINT("[input] ctrl_open_inputs[%d] %s\n",i,urls[i].text());
    if (urls[i].empty()) continue;

    /// Open Input
    input=open_input(urls[i]);
    if (input==NULL) {
      if (aborted()) break;
      continue;
      }

    /// Open Reader
    reader = open_reader();
    if (reader==NULL) continue;

    if (!reader->init(input))
      continue;

    streamid++;
    set_state(StateProcessing,true);
    return;
    }
  ctrl_close_input();
  set_state(StateIdle,true);
  }
Beispiel #8
0
long GMNotifyDaemon::onNotifyCapabilities(FXObject*,FXSelector,void*ptr){
  DBusMessage * msg = static_cast<DBusMessage*>(ptr);
  FXchar ** caps = NULL;
  int ncaps;
  if ((dbus_message_get_type(msg)==DBUS_MESSAGE_TYPE_METHOD_RETURN) && dbus_message_get_args(msg,NULL,DBUS_TYPE_ARRAY,DBUS_TYPE_STRING,&caps,&ncaps,DBUS_TYPE_INVALID)) {
    FXbool has_action_icons=false;
    FXbool has_actions=false;
    FXbool has_persistence=false;

    for (FXint i=0;i<ncaps;i++){
      GM_DEBUG_PRINT("caps[%d]=%s\n",i,caps[i]);
      if (flags&ACTION_ITEMS) {
        if (comparecase(caps[i],"actions")==0)
          has_actions=true;
        else if ((comparecase(caps[i],"action-icons")==0) || (comparecase(caps[i],"x-gnome-icon-buttons")==0))
          has_action_icons=true;
        else if (comparecase(caps[i],"persistence")==0)
          has_persistence=true;
        }
      }

    if (has_actions && has_action_icons && has_persistence) {
      persistent=true;
      reset();
      }

    // Need to delete array of strings returned by dbus_message_get_args
    dbus_free_string_array(caps);
    }
  return 1;
  }
void InputThread::ctrl_open_input(const FXString & uri) {
  GM_DEBUG_PRINT("[input] ctrl_open_input %s\n",uri.text());

  if (uri.empty()) {
    goto failed;
    }

  /// Open Input
  input=open_input(uri);
  if (input==NULL) {
    engine->post(new ErrorMessage(FXString::value("Unable to open %s",uri.text())));
    goto failed;
    }

  reader = open_reader();
  if (reader==NULL) {
    engine->post(new ErrorMessage(FXString::value("No input plugin available for %s",uri.text())));
    goto failed;
    }

  if (!reader->init(input)) {
    engine->post(new ErrorMessage(FXString::value("Failed to initialize plugin")));
    goto failed;
    }

  streamid++;
  set_state(StateProcessing,true);
  return;
failed:
  ctrl_close_input();
  set_state(StateIdle,true);
  }
Beispiel #10
0
FXbool VorbisDecoder::init_decoder() {
  const FXuchar * data_ptr = get_packet_offset();

  // Initialize Info
  init_info();

  while(get_next_packet()) {
    if (is_vorbis_header()) {
      if (vorbis_synthesis_headerin(&info,&comment,&op)<0) {
        GM_DEBUG_PRINT("[vorbis] vorbis_synthesis_headerin failed\n");
        return false;
        }
      }
    else { // First non header

      if (vorbis_synthesis_init(&dsp,&info)<0)
        return false;

      if (vorbis_block_init(&dsp,&block)<0) {
        vorbis_dsp_clear(&dsp);
        return false;
        }

      has_dsp=true;
      push_back_packet();
      return true;
      }
    }

  vorbis_info_clear(&info);

  set_packet_offset(data_ptr);
  return true;
  }
Beispiel #11
0
void HttpClient::discard() {
  GM_DEBUG_PRINT("[http] discard()\n");
  if (flags&ConnectionClose) {
    close();
    }
  else if (io.isOpen()) {
    HttpResponse::discard();
    }
  }
Beispiel #12
0
ReadStatus MP4Reader::parse() {
  mp4AudioSpecificConfig cfg;
  FXuchar* buffer;
  FXuint   size;
  FXint    ntracks;

  FXASSERT(handle==NULL);
  FXASSERT(packet);

  handle = mp4ff_open_read(&callback);
  if (handle==NULL)
    goto error;

  ntracks = mp4ff_total_tracks(handle);
  if (ntracks<=0)
    goto error;

  for (FXint i=0;i<ntracks;i++) {
    if ((mp4ff_get_decoder_config(handle,i,&buffer,&size)==0) && buffer && size) {
      if (NeAACDecAudioSpecificConfig(buffer,size,&cfg)==0) {

        af.set(AP_FORMAT_S16,mp4ff_get_sample_rate(handle,i),mp4ff_get_channel_count(handle,i));
        af.debug();

        if (size>packet->space()) {
          GM_DEBUG_PRINT("MP4 config buffer is too big for decoder packet");
          free(buffer);
          goto error;
          }

        track=i;
        frame=0;
        nframes=mp4ff_num_samples(handle,i);
        stream_length=mp4ff_get_track_duration(handle,i);


        packet->append(buffer,size);
        packet->flags|=AAC_FLAG_CONFIG|AAC_FLAG_FRAME;
        engine->decoder->post(new ConfigureEvent(af,Codec::AAC));

        send_meta();

        engine->decoder->post(packet);

        packet=NULL;
        flags|=FLAG_PARSED;
        free(buffer);
        return ReadOk;
        }
      free(buffer);
      }
    }

error:
  packet->unref();
  return ReadError;
  }
Beispiel #13
0
void AudioEngine::exit() {
  if (input->running()) {

    GM_DEBUG_PRINT("AudioEngine::exit()\n");

    input->post(new ControlEvent(Ctrl_Quit),EventQueue::Flush);

    GM_DEBUG_PRINT("Waiting for input\n");
    input->join();
    GM_DEBUG_PRINT("Waiting for decoder\n");
    decoder->join();
    GM_DEBUG_PRINT("Waiting for output\n");
    output->join();
    GM_DEBUG_PRINT("All Joined. Freeing data\n");
    input->free();
    decoder->free();
    output->free();
    }
  }
Beispiel #14
0
FXbool PulseOutput::open() {

  /// Start the mainloop
  //if (eventloop==nullptr) {
   // eventloop = new PulseReactor();
   // }

  /// Get a context
  if (pulse_context==nullptr) {
    pulse_context = pa_context_new(&api,"Goggles Music Manager");
#ifdef DEBUG
    pa_context_set_state_callback(pulse_context,context_state_callback,this);
#endif
    pa_context_set_subscribe_callback(pulse_context,context_subscribe_callback,this);
    }

  /// Try connecting
  GM_DEBUG_PRINT("[pulse] pa_context_connect()\n");
  if (pa_context_get_state(pulse_context)==PA_CONTEXT_UNCONNECTED) {
    if (pa_context_connect(pulse_context,nullptr,PA_CONTEXT_NOFLAGS,nullptr)<0) {
      GM_DEBUG_PRINT("[pulse] pa_context_connect failed\n");
      return false;
      }
    }

  /// Wait until we're connected to the pulse daemon
  GM_DEBUG_PRINT("[pulse] wait for connection\n");
  pa_context_state_t state;
  while((state=pa_context_get_state(pulse_context))!=PA_CONTEXT_READY) {
    if (state==PA_CONTEXT_FAILED || state==PA_CONTEXT_TERMINATED){
      GM_DEBUG_PRINT("[pulse] Unable to connect to pulsedaemon\n");
      return false;
      }
    context->wait_plugin_events();
    }

  pa_operation* operation = pa_context_subscribe(pulse_context,PA_SUBSCRIPTION_MASK_SINK_INPUT,nullptr,this);
  if (operation) pa_operation_unref(operation);


  GM_DEBUG_PRINT("[pulse] ready()\n");
  return true;
  }
Beispiel #15
0
void InputThread::set_state(FXuchar s,FXbool notify) {
  if (state!=s) {
    state=s;
    switch(state) {
      case StateIdle      : GM_DEBUG_PRINT("[input] state = idle\n");       break;
      case StateProcessing: GM_DEBUG_PRINT("[input] state = processing\n"); break;
      case StateError     : GM_DEBUG_PRINT("[input] state = error\n");      break;
      }
    }

  /// Tell front end about the state.
  if (notify) {
    switch(state) {
      case StateError     :
      case StateIdle      : engine->post(new Event(AP_STATE_READY));   break;
      case StateProcessing: engine->post(new Event(AP_STATE_PLAYING)); break;
      default       : break;
      }
    }
  }
Beispiel #16
0
void InputThread::ctrl_close_input(FXbool notify) {
  GM_DEBUG_PRINT("[input] close input %d\n",notify);
  if (input) {
    delete input;
    input=NULL;
    url.clear();
    }
  if (reader) {
    delete reader;
    reader=NULL;
    }
  set_state(StateIdle,notify);
  }
Beispiel #17
0
void GMNotifyDaemon::close() {
  if (msgid>0) {
    GM_DEBUG_PRINT("GMNotifyDaemon::close()\n");
    DBusMessage * msg = method("CloseNotification");
    if (msg) {
      dbus_message_append_args(msg,DBUS_TYPE_UINT32,&msgid,DBUS_TYPE_INVALID);
      dbus_message_set_no_reply(msg,true);
      bus->send(msg);
      // We don't want to wait for NotificationClosed signal.
      // and we want to prevent calling CloseNotification multiple times.
      msgid=0;
      }
    }
  }
Beispiel #18
0
ReadStatus AACReader::process(Packet*packet) {
  if (!(flags&FLAG_PARSED)) {
    GM_DEBUG_PRINT("finding sync\n");
    FXuchar buffer[2];
    if (input->read(buffer,2)!=2)
      return ReadError;
    do {
//      fxmessage("0x%hhx  0x%hhx\n",buffer[0],buffer[1]);
      if ((buffer[0]==0xFF) && (buffer[1]&0xf0)==0xf0) {
        GM_DEBUG_PRINT("found sync\n");
 //       af.set(AP_FORMAT_S16,44100,2);
        engine->decoder->post(new ConfigureEvent(af,Codec::AAC));
        flags|=FLAG_PARSED;
        packet->append(buffer,2);
        break;
        }
      buffer[0]=buffer[1];
      if (input->read(&buffer[1],1)!=1)
        return ReadError;
      }
    while(1);
    }
  return ReaderPlugin::process(packet);
  }
Beispiel #19
0
FXint GMRenameTask::run() {
  try {
    for (FXint i=0;i<from.no() && processing;i++) {
      if (to[i].empty()) continue;
      if (!FXDir::createDirectories(FXPath::directory(to[i]))) continue;
      if (FXStat::exists(to[i])) continue;
      if (FXFile::moveFiles(from[i],to[i])){
        database->setTrackFilename(tracks[i],to[i]);
        }
      }
    }
  catch(GMDatabaseException&) {
    GM_DEBUG_PRINT("Database Exception\n");
    }
  return 0;
  }
Beispiel #20
0
void WavOutput::close() {
  if (file.isOpen()) {
    GM_DEBUG_PRINT("[wav] closed output\n");
    FXulong end=file.position();
    FXulong size;
    FXuint size32=0xFFFFFFFF;

    size=end-8;
    if (end>0xFFFFFFFF) {

      // RIFF Chunk
      file.position(0);
      file.writeBlock("RF64",4);
      file.writeBlock(&size32,4);

      // DS64 Chunk
      file.position(12);
      file.writeBlock("ds64",4);
      file.position(20);
      file.writeBlock(&size,8);
      // Data Chunk
      if (data_pos) {
        size=end-data_pos-4;
        file.writeBlock(&size,8);
        size=0;
        file.writeBlock(&size,8);
        }
      }
    else {

      /// RIFF chunksize
      size32=size;
      file.position(4);
      file.writeBlock(&size32,4);

      // Data Chunksize
      if (data_pos) {
        file.position(data_pos);
        size=end-data_pos-4;
        file.writeBlock(&size,4);
        }
      }
    file.close();
    }
  af.reset();
  }
Beispiel #21
0
FXbool HttpClient::open_connection() {
  GM_DEBUG_PRINT("[http] open_connection()\n");
  FXIO * stream = NULL;

  if (connection==NULL)
    connection = new ConnectionFactory();

  if (options&UseProxy)
    stream = connection->open(proxy.name.text(),proxy.port);
  else
    stream = connection->open(server.name.text(),server.port);

  if (stream) {
    io.attach(stream);
    return true;
    }
  return false;
  }
Beispiel #22
0
void ID3V2::parse_text_frame(FXuint frameid,FXint framesize) {
  FXString text;
  const FXuchar & encoding = buffer[p];

  parse_text(encoding,(const FXchar*)buffer+p+1,framesize-1,text);

  GM_DEBUG_PRINT("[id3v2] text: \"%s\"\n",text.text());

  switch(frameid) {
    case TP1  :
    case TPE1 : artist.adopt(text); break;
    case TAL  :
    case TALB : album.adopt(text); break;
    case TT2  :
    case TIT2 : title.adopt(text); break;
    default   : break;
    }
  }
Beispiel #23
0
long GMNotifyDaemon::onSignal(FXObject*,FXSelector,void*ptr){
  DBusMessage * msg = static_cast<DBusMessage*>(ptr);
  FXuint id,reason;
  FXchar * action;
  if (dbus_message_is_signal(msg,GALAGO_NOTIFY_INTERFACE,"NotificationClosed")){
    if ((dbus_message_has_signature(msg,"u") && dbus_message_get_args(msg,NULL,DBUS_TYPE_UINT32,&id,DBUS_TYPE_INVALID)) ||
        (dbus_message_has_signature(msg,"uu") && dbus_message_get_args(msg,NULL,DBUS_TYPE_UINT32,&id,DBUS_TYPE_UINT32,&reason,DBUS_TYPE_INVALID))) {
      if (id==msgid) {
        msgid=0;
        }
      }
    return 1;
    }
  else if (dbus_message_is_signal(msg,GALAGO_NOTIFY_INTERFACE,"ActionInvoked")){
    if (dbus_message_has_signature(msg,"us") && dbus_message_get_args(msg,NULL,DBUS_TYPE_UINT32,&id,DBUS_TYPE_STRING,&action,DBUS_TYPE_INVALID)) {
      if (compare(action,"media-skip-backward")==0) {
        GMPlayerManager::instance()->cmd_prev();
        }
      else if (compare(action,"media-skip-forward")==0) {
        GMPlayerManager::instance()->cmd_next();
        }
      else if (compare(action,"media-playback-pause")==0) {
        GMPlayerManager::instance()->cmd_pause();
        }
      else if (compare(action,"media-playback-start")==0) {
        GMPlayerManager::instance()->cmd_play();
        }
      else if (compare(action,"media-playback-stop")==0) {
        GMPlayerManager::instance()->cmd_stop();
        }
      else {
        GM_DEBUG_PRINT("unhandled action: %s\n",action);
        }
      return 1;
      }
    }
  return 0;
  }
Beispiel #24
0
ReadStatus TextReader::process(Packet*packet) {
  packet->unref();
  GM_DEBUG_PRINT("[text] starting read %ld\n",input->size());
  if (input->size()>0) {
    textbuffer.length(input->size());
    if (input->read(textbuffer.text(),input->size())!=input->size())
      return ReadError;
    }
  else {
    FXint len=0,nread=0;
    const FXint chunk=4096;
    do {
      len+=nread;
      textbuffer.length(textbuffer.length()+chunk);
      nread=input->read(&textbuffer[len],chunk);
      }
    while(nread>0);
    textbuffer.trunc(len);
    if (nread==-1)
      return ReadError;
    }
  return ReadDone;
  }
Beispiel #25
0
FXbool PulseOutput::configure(const AudioFormat & fmt){
  const pa_sample_spec * config=nullptr;
  pa_operation *operation=nullptr;

  if (!open())
    return false;

  if (stream && fmt==af)
    return true;

  if (stream) {
    pa_stream_disconnect(stream);
    pa_stream_unref(stream);
    stream=nullptr;
    }

  pa_sample_spec spec;
  pa_channel_map cmap;

  if (!to_pulse_format(fmt,spec.format))
    goto failed;

  spec.rate     = fmt.rate;
  spec.channels = fmt.channels;


  // setup channel map
  pa_channel_map_init(&cmap);
  cmap.channels = fmt.channels;
  for (FXint i=0;i<fmt.channels;i++) {
    switch(fmt.channeltype(i)) {
      case Channel::None        : cmap.map[i] = PA_CHANNEL_POSITION_INVALID;      break;
      case Channel::Mono        : cmap.map[i] = PA_CHANNEL_POSITION_MONO;         break;
      case Channel::FrontLeft   : cmap.map[i] = PA_CHANNEL_POSITION_FRONT_LEFT;   break;
      case Channel::FrontRight  : cmap.map[i] = PA_CHANNEL_POSITION_FRONT_RIGHT;  break;
      case Channel::FrontCenter : cmap.map[i] = PA_CHANNEL_POSITION_FRONT_CENTER; break;
      case Channel::BackLeft    : cmap.map[i] = PA_CHANNEL_POSITION_REAR_LEFT;    break;
      case Channel::BackRight   : cmap.map[i] = PA_CHANNEL_POSITION_REAR_RIGHT;   break;
      case Channel::BackCenter  : cmap.map[i] = PA_CHANNEL_POSITION_REAR_CENTER;  break;
      case Channel::SideLeft    : cmap.map[i] = PA_CHANNEL_POSITION_SIDE_LEFT;    break;
      case Channel::SideRight   : cmap.map[i] = PA_CHANNEL_POSITION_SIDE_RIGHT;   break;
      case Channel::LFE         : cmap.map[i] = PA_CHANNEL_POSITION_LFE;          break;
      default: goto failed;
      }
    }

  stream = pa_stream_new(pulse_context,"Goggles Music Manager",&spec,&cmap);
  if (stream == nullptr)
    goto failed;

#ifdef DEBUG
  pa_stream_set_state_callback(stream,stream_state_callback,this);
#endif
  //pa_stream_set_write_callback(stream,stream_write_callback,this);

  if (pa_stream_connect_playback(stream,nullptr,nullptr,PA_STREAM_NOFLAGS,nullptr,nullptr)<0)
    goto failed;

  /// Wait until stream is ready
  pa_stream_state_t state;
  while((state=pa_stream_get_state(stream))!=PA_STREAM_READY) {
    if (state==PA_STREAM_FAILED || state==PA_STREAM_TERMINATED){
      goto failed;
      }
    context->wait_plugin_events();
    }

  /// Get Actual Format
  config = pa_stream_get_sample_spec(stream);
  if (!to_gap_format(config->format,af))
    goto failed;
  af.channels=config->channels;
  af.rate=config->rate;
  af.channelmap=fmt.channelmap;

  /// Get Current Volume
  operation = pa_context_get_sink_input_info(pulse_context,pa_stream_get_index(stream),sink_info_callback,this);
  if (operation) pa_operation_unref(operation);

  return true;
failed:
  GM_DEBUG_PRINT("[pulse] Unsupported pulse configuration:\n");
  fmt.debug();
  return false;
  }
Beispiel #26
0
///FIXME perhaps support extensible wav format
FXbool WavOutput::configure(const AudioFormat & fmt) {
  FXushort format;

  // Can't handle big endian yet, neither does the output thread handle byteorder swaps
  if (fmt.byteorder() != Format::Little)
    return false;

  // Extensible Wav Format not yet supported
  if (fmt.channels>2)
    return false;

  // Determine format
  switch(fmt.datatype()) {
    case Format::Unsigned :
    case Format::Signed   : format = WAV_FORMAT_PCM;  break;
    case Format::Float    : format = WAV_FORMAT_FLOAT; break;
    default               : return false; break;
    }

  FXString path=FXPath::unique("gap.wav");
  if (file.open(path,FXIO::Writing)) {
    GM_DEBUG_PRINT("[wav] opened output file: %s\n",path.text());
    af=fmt;
    FXuint chunksize=0;
    FXlong ldata=0;

    /// riff chunk
    file.writeBlock("RIFF",4);
    file.writeBlock(&chunksize,4); // empty for now
    file.writeBlock("WAVE",4);

    /// junk chunk
    chunksize=28;
    file.writeBlock("JUNK",4);
    file.writeBlock(&chunksize,4);
    file.writeBlock(&ldata,8);
    file.writeBlock(&ldata,8);
    file.writeBlock(&ldata,8);
    chunksize=0;
    file.writeBlock(&chunksize,4);

    /// fmt
    file.writeBlock("fmt ",4);
    chunksize=16;
    file.writeBlock(&chunksize,4);
    file.writeBlock(&format,2);

    FXushort channels=fmt.channels;
    FXuint   rate=fmt.rate;
    FXuint   byterate=fmt.rate*fmt.channels*fmt.packing();
    FXushort blockalign=fmt.framesize();
    FXushort bitspersample=fmt.bps();

    file.writeBlock(&channels,2);
    file.writeBlock(&rate,4);
    file.writeBlock(&byterate,4);
    file.writeBlock(&blockalign,2);
    file.writeBlock(&bitspersample,2);

    file.writeBlock("data",4);
    chunksize=0xFFFFFFFF;
    data_pos=file.position();
    file.writeBlock(&chunksize,4);
    return true;
    }
  GM_DEBUG_PRINT("[wav] failed to open output file: %s\n",path.text());
  return false;
  }
Beispiel #27
0
void InputThread::ctrl_flush(FXbool close){
  GM_DEBUG_PRINT("[input] flush\n");
  engine->decoder->post(new FlushEvent(close),EventQueue::Flush);
  }
Beispiel #28
0
DecoderStatus VorbisDecoder::process(Packet * packet) {
  FXASSERT(packet);

#ifdef HAVE_VORBIS_PLUGIN
  FXfloat ** pcm=NULL;
  FXfloat * buf32=NULL;
#else // HAVE_TREMOR_PLUGIN
  FXint ** pcm=NULL;
  FXshort * buf32=NULL;
#endif

  FXint p,navail=0;

  FXint ngiven,ntotalsamples,nsamples,sample,c,s;

  FXbool  eos=packet->flags&FLAG_EOS;
  FXuint   id=packet->stream;
  FXlong  len=packet->stream_length;


  OggDecoder::process(packet);

  /// Init Decoder
  if (!has_dsp) {
    if (!init_decoder())
      return DecoderError;
    if (!has_dsp)
      return DecoderOk;
    }

  /// Find Stream Position
  if (stream_position==-1 && !find_stream_position())
    return DecoderOk;


  if (out) {
    navail = out->availableFrames();
    }

  while(get_next_packet()) {

    if (__unlikely(is_vorbis_header())) {
      GM_DEBUG_PRINT("[vorbis] unexpected vorbis header found. Resetting decoder\n");
      push_back_packet();
      reset_decoder();
      return DecoderOk;
      }

    if (vorbis_synthesis(&block,&op)==0)
      vorbis_synthesis_blockin(&dsp,&block);

    while((ngiven=vorbis_synthesis_pcmout(&dsp,&pcm))>0) {
      if (len>0) FXASSERT(stream_position+ngiven<=len);

      if (__unlikely(stream_position<stream_decode_offset)) {
        FXlong offset = FXMIN(ngiven,stream_decode_offset - stream_position);
        GM_DEBUG_PRINT("[vorbis] stream decode offset %ld. Skipping %ld of %ld \n",stream_decode_offset,offset,stream_decode_offset-stream_position);
        ngiven-=offset;
        stream_position+=offset;
        sample=offset;
        vorbis_synthesis_read(&dsp,offset);
        if (ngiven==0) continue;
        }
      else {
        sample=0;
        }

      for (ntotalsamples=ngiven;ntotalsamples>0;) {

        /// Get new buffer
        if (out==NULL) {
          out = engine->decoder->get_output_packet();
          if (out==NULL) return DecoderInterrupted;
          out->stream_position=stream_position;
          out->stream_length=len;
          out->af=af;
          navail = out->availableFrames();
          }

#ifdef HAVE_VORBIS_PLUGIN
        buf32 = out->flt();
#else // HAVE_TREMOR_PLUGIN
        buf32 = out->s16();
#endif
        /// Copy Samples
        nsamples = FXMIN(ntotalsamples,navail);
        for (p=0,s=sample;s<(nsamples+sample);s++){
          for (c=0;c<info.channels;c++,p++) {
#ifdef HAVE_VORBIS_PLUGIN
            buf32[p]=pcm[c][s];
#else
            buf32[p]=CLIP_TO_15(pcm[c][s]>>9);
#endif
            }
          }

        /// Update sample counts
        out->wroteFrames(nsamples);

        sample+=nsamples;
        navail-=nsamples;
        ntotalsamples-=nsamples;
        stream_position+=nsamples;

        /// Send out packet if full
        ///FIXME handle EOS.
        if (navail==0) {
          engine->output->post(out);
          out=NULL;
          }
        }
      vorbis_synthesis_read(&dsp,ngiven);
      }
    }

  if (eos) {
    if (out && out->numFrames())  {
      engine->output->post(out);
      out=NULL;
      }
    engine->output->post(new ControlEvent(End,id));
    }
  return DecoderOk;
  }
Beispiel #29
0
DecoderStatus AacDecoder::process(Packet*packet){
  FXlong fs  = packet->stream_position;
  FXbool eos = packet->flags&FLAG_EOS;

  long unsigned int samplerate;
  FXuchar           channels;
  NeAACDecFrameInfo frame;

  if (packet->flags&AAC_FLAG_CONFIG) {
    handle = NeAACDecOpen();
    if (NeAACDecInit2(handle,packet->data(),packet->size(),&samplerate,&channels)<0){
      packet->unref();
      return DecoderError;
      }
    return DecoderOk;
    }
  else {
    buffer.append(packet->data(),packet->size());
    packet->unref();
    if (handle==NULL) {
      handle = NeAACDecOpen();
      long n = NeAACDecInit(handle,buffer.data(),buffer.size(),&samplerate,&channels);
      if (n<0) return DecoderError;
      else if (n>0) buffer.readBytes(n);

      af.set(AP_FORMAT_S16,samplerate,channels);
      engine->output->post(new ConfigureEvent(af,Codec::AAC));
      }
    }

  if (buffer.size()<FAAD_MIN_STREAMSIZE*2) {
    return DecoderOk;
    }


  do {

    if (out==NULL){
      out = engine->decoder->get_output_packet();
      if (out==NULL) return DecoderInterrupted;
      out->af              = af;
      out->stream_position = fs;
      out->stream_length   = packet->stream_length;
      }

    void * outbuffer = out->ptr();
    NeAACDecDecode2(handle,&frame,buffer.data(),buffer.size(),&outbuffer,out->availableFrames()*out->af.framesize());
    if (frame.bytesconsumed>0) {
      buffer.readBytes(frame.bytesconsumed);
      }

	  if (frame.error > 0) {
	    GM_DEBUG_PRINT("[aac] error %d (%ld): %s\n",frame.error,frame.bytesconsumed,faacDecGetErrorMessage(frame.error));
	    }

    if (frame.samples) {
      fs+=(frame.samples/frame.channels);
      out->wroteFrames((frame.samples/frame.channels));
      if (out->availableFrames()==0) {
        engine->output->post(out);
        out=NULL;
        }
      }
    }
  while(buffer.size()>(2*FAAD_MIN_STREAMSIZE) && frame.bytesconsumed);

  if (eos) {
    if (out) {
      engine->output->post(out);
      out=NULL;
      }
    engine->output->post(new ControlEvent(End,packet->stream));
    }

  return DecoderOk;
  }
Beispiel #30
0
FXint InputThread::run(){
  Event * event;

  ap_set_thread_name("ap_input");

  for (;;) {
    if (reader && state==StateProcessing)
      event = wait_for_packet();
    else
      event = wait_for_event();

    switch(event->type) {
      case Ctrl_Close     : ctrl_flush(true);
                            ctrl_close_input(true);
                            break;

      case Ctrl_Open_Flush: ctrl_flush();
      case Ctrl_Open      : ctrl_open_input(((ControlEvent*)event)->text);
                            break;

      case Ctrl_Quit      : ctrl_close_input(true);
                            engine->decoder->post(event,EventQueue::Flush);
                            return 0;
                            break;
      case Ctrl_Seek      : ctrl_seek(((CtrlSeekEvent*)event)->pos);
                            break;
      case End            : if (event->stream==streamid) {
                              ctrl_eos();
                              }
                            break;
      case Meta           : engine->decoder->post(event);
                            continue;
                            break;
      case AP_EOS         : GM_DEBUG_PRINT("[input] eos\n");
                            if (state!=StateError) {
                              engine->post(event);
                              continue;
                              }
                            break;
      case Buffer         :
        {
          Packet * packet = dynamic_cast<Packet*>(event);
          FXASSERT(reader);
          FXASSERT(packet);
          packet->stream = streamid;
          FXuint status = reader->process(packet);
          switch(status) {
            case ReadError    : GM_DEBUG_PRINT("[input] error\n");
                                ctrl_close_input();
                                set_state(StateError,true);
                                break;
            case ReadDone     : GM_DEBUG_PRINT("[input] done\n");
                                set_state(StateIdle);
                                break;
            case ReadRedirect : {GM_DEBUG_PRINT("[input] redirect\n");
                                FXStringList list;
                                reader->redirect(list);
                                ctrl_open_inputs(list);
                                }
                                break;
            default         : break;
            }
          continue; /* packet already released */
          break;
        }
      }
    Event::unref(event);
    }
  return 0;
  }