I have some code below that basically initialises PortAudio and opens an Ogg file specifed as argv[1]. Not sure what to do next. The PortAudio tutorials on their site are very limited and the example code included with V19 only covers testing audio, finding devices, testing latency, and generating tones.

I am pretty sure it's not PortAudio that is the problem here, but what to do PortAudio's callback regarding audio data that is given from libvorbisfile.

Audacity and Mixxx are a few example programs using PortAudio successfully but they have not been helpful as their implementations seem to be very specific. I also have tried to understand mpg123's PA implementation.

So what do I pass? Code below.

Code:
/* Compile with:  gcc -o portogg -D__DEBUG__ -Wall -ansi -pedantic -std=c99 -Wfatal-errors -lportaudio -lvorbisfile portogg.c */
 
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <portaudio.h>
#include <vorbis/vorbisfile.h>
 
#define INPUTCHANNELS 0
#define BYTES_TO_READ 4096
 
typedef struct {
  struct OggVorbis_File file;
  struct vorbis_info *info;
  double audio_length;
  int endian;
  int position;
} audioData_s;
 
static int oggCallback(const void *inputBuffer,
                void *outputBuffer,
                unsigned long framesPerBuffer,
                const PaStreamCallbackTimeInfo *timeInfo,
                const PaStreamCallbackFlags statusFlags,
                void *userData ) {
  (void)inputBuffer; /* Prevent unused variable warnings */
  audioData_s *data = (audioData_s*)userData;
  char *out = (char*)outputBuffer;
  long ret;
 
  ret = ov_read(&data->file, out, BYTES_TO_READ, data->endian, data->info->channels, 1, &data->position);
  fprintf(stdout, "ret = %ld\n", ret);
  if (ret == 0)
    return 1;
 
  return 0;
}
 
int main(int argc, char *argv[]) {
  if (argc != 2) {
    fprintf(stderr, "Usage: %s <ogg file>\n", argv[0]);
    exit(EXIT_FAILURE);
  }
 
  PaError err; /* PortAudio types */
  PaStream *stream;
 
  audioData_s audioData;
  FILE *ogg;
  bool streamFailure = false;
  int testvar = 1; /* Endianness */
 
  if ((err = Pa_Initialize()) != paNoError) {
    fprintf(stderr, "Pa_Initialize() returned an error: %s\n",
            Pa_GetErrorText(err));
    exit(EXIT_FAILURE);
  }
 
  ogg = fopen(argv[1], "rb");
  if (ov_open(ogg, &audioData.file, NULL, 0) < 0) {
    fprintf(stderr, "Error decoding %s.\n", argv[1]);
    exit(EXIT_FAILURE);
  }
 
  audioData.info = ov_info(&audioData.file, -1);  /* Information about Ogg file */
  audioData.audio_length = ov_time_total(&audioData.file, -1);
 
#ifdef __DEBUG__
  fprintf(stdout, "Ogg filename: %s\n", argv[1]);
  fprintf(stdout, "Sample rate: %ld\n", audioData.info->rate);
  fprintf(stdout, "Number of channels: %d\n", audioData.info->channels);
  fprintf(stdout, "Lenght: %.3f seconds\n", audioData.audio_length);
#endif
 
  if (ov_pcm_seek(&audioData.file, 0) != 0) { /* This is because some files do not do this automatically */
    fprintf(stderr, "Error seeking file to position 0.\n");
  }
  else {
#ifdef __DEBUG__
    fprintf(stdout, "Seeked file to position 0.\n");
#endif
    audioData.position = 0;
  }
 
  err = Pa_OpenDefaultStream(&stream,
                             INPUTCHANNELS,
                             audioData.info->channels,
                             paFloat32,
                             audioData.info->rate,
                             BYTES_TO_READ,
                             oggCallback,
                             &audioData);
  if (err != paNoError) {
    fprintf(stderr, "Pa_OpenDefaultStream() returned an error: %s\n", Pa_GetErrorText(err));
    streamFailure = true;
  }
 
  if(*(char *)&testvar)
    audioData.endian = 0;  /* little endian */
  else
    audioData.endian = 1;  /* big endian */
 
  err = Pa_StartStream( stream );
  if( err != paNoError )
    fprintf(stderr, "Error starting stream.\n");
#ifdef __DEBUG__
  else
    fprintf(stdout, "Stream started successfully.\n");
#endif
 
  /* Call back starts now */
  Pa_Sleep(1000*(int)audioData.audio_length);
 
  err = Pa_StopStream( stream );
  if( err != paNoError )
    fprintf(stderr, "Error stopping stream: %s\n", Pa_GetErrorText(err));
#ifdef __DEBUG__
  else
    fprintf(stdout, "Stream stopped successfully.\n");
#endif
 
  err = Pa_CloseStream( stream );
  if( err != paNoError )
    fprintf(stderr, "Error closing stream: %s\n", Pa_GetErrorText(err));
#ifdef __DEBUG__
  else
    fprintf(stdout, "Stream closed successfully.\n");
#endif
 
  ov_clear(&audioData.file);
#ifdef __DEBUG__
  fprintf(stdout, "Freed %s file from memory.\n", argv[1]);
#endif
 
  err = Pa_Terminate();
  if( err != paNoError )
    fprintf(stderr, "PortAudio error: %s\n", Pa_GetErrorText(err));
#ifdef __DEBUG__
  else
    fprintf(stdout, "PortAudio terminated.\n");
#endif
 
  if (streamFailure)
    exit(EXIT_FAILURE);
 
  exit(EXIT_SUCCESS);
}
EDIT: Now plays sound, but not good sound. How do I advance in the file?