/**********
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)

This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
more details.

You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**********/
// Copyright (c) 1996-2020, Live Networks, Inc.  All rights reserved
// A test program that reads a ".mkv" (i.e., Matroska) file, demultiplexes each track
// (video, audio, subtitles), and outputs each track to a file.
// main program

#include <liveMedia.hh>
#include <BasicUsageEnvironment.hh>

UsageEnvironment* env;
char const* programName;
char const* inputFileName;

// An array of structures representing the state of the video, audio, and subtitle tracks:
static struct {
  unsigned trackNumber;
  FramedSource* source;
  FileSink* sink;
} trackState[3];

void onMatroskaFileCreation(MatroskaFile* newFile, void* clientData); // forward

void usage() {
  *env << "usage: " << programName << " <input-Matroska-or-WebM-file-name>\n";
  exit(1);
}

int main(int argc, char** argv) {
  // Begin by setting up our usage environment:
  TaskScheduler* scheduler = BasicTaskScheduler::createNew();
  env = BasicUsageEnvironment::createNew(*scheduler);

  // Parse the command line:
  programName = argv[0];
  if (argc != 2) usage();
  inputFileName = argv[1];

  // Arrange to create a "MatroskaFile" object for the specified file.
  // (Note that this object is not created immediately, but instead via a callback.)
  MatroskaFile::createNew(*env, inputFileName, onMatroskaFileCreation, NULL);

  env->taskScheduler().doEventLoop(); // does not return

  return 0; // only to prevent compiler warning
}

void play(); // forward

void onMatroskaFileCreation(MatroskaFile* matroskaFile, void* /*clientData*/) {
  // Create a new demultiplexor for the file:
  MatroskaDemux* matroskaDemux = matroskaFile->newDemux();

  // Create source streams and file sinks for each preferred track;

  unsigned numActiveTracks = 0;
  for (unsigned i = 0; i < 3; ++i) {
    unsigned trackNumber;
    trackState[i].source = matroskaDemux->newDemuxedTrack(trackNumber);
    trackState[i].trackNumber = trackNumber;
    trackState[i].sink = NULL; // by default; may get changed below
    
    if (trackState[i].source == NULL) continue;
    
    char const* mimeType = matroskaFile->trackMIMEType(trackNumber);
    if (mimeType == NULL || mimeType[0] == '\0') continue;
    fprintf(stderr, "#####@@@@@ MatroskaDemuxedTrack for mimeType %s is %p\n", mimeType, trackState[i].source);

    // Create the file name from "mimeType" by replacing "/" with "-", and adding the
    // track number at the end:
    char* fileName = new char[strlen(mimeType) + 100/*more than enough space*/];
    sprintf(fileName, "%s-%d", mimeType, trackNumber);
    for (unsigned j = 0; fileName[j] != '\0'; ++j) {
      if (fileName[j] == '/') {
	fileName[j] = '-';
	break;
      }
    }

    trackState[i].sink
	= matroskaFile->createFileSinkForTrackNumber(trackNumber, fileName);
    if (trackState[i].sink != NULL) {
      ++numActiveTracks;
      fprintf(stderr, "Created output file \"%s\" for track %d\n", fileName, trackNumber);
    }
  }

  if (numActiveTracks == 0) {
    *env << "Error: The Matroska file \"" << inputFileName << "\" has no streamable tracks\n";
    *env << "(Perhaps the file does not exist, or is not a 'Matroska' file.)\n";
    exit(1);
  }

  // Start the streaming:
  play();
}

void afterPlaying(void* /*clientData*/) {
  *env << "...done reading from file\n";

  // Stop playing all sinks, then close the source streams
  // (which will also close the demultiplexor itself):
  unsigned i;
  for (i = 0; i < 3; ++i) {
    if (trackState[i].sink != NULL) trackState[i].sink->stopPlaying();
    Medium::close(trackState[i].source); trackState[i].source = NULL;
  }

  // Finally, close the sinks:
  for (i = 0; i < 3; ++i) Medium::close(trackState[i].sink);

  exit(0);
}

void play() {
  *env << "Beginning to read from file...\n";

  // Start playing each track's RTP sink from its corresponding source:
  for (unsigned i = 0; i < 3; ++i) {
    if (trackState[i].sink != NULL && trackState[i].source != NULL) {
      trackState[i].sink->startPlaying(*trackState[i].source, afterPlaying, NULL);
    }
  }
}
