text: /*
   * menu_ffmpeg.c - FFMPEG menu for SDL UI.
   *
   * Written by
   *  Hannu Nuotio <hannu.nuotio@tut.fi>
   *
   * This file is part of VICE, the Versatile Commodore Emulator.
   * See README for copyright notice.
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or
   *  (at your option) any later version.
   *
   *  This program 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 General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program; if not, write to the Free Software
   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   *  02111-1307  USA.
   *
   */
  
  #include "vice.h"
  
  #ifdef HAVE_FFMPEG
  
  #include <stdio.h>
  #include <string.h>
  
  #include "types.h"
  
  #include "gfxoutput.h"
  #include "lib.h"
  #include "menu_common.h"
  #include "menu_ffmpeg.h"
  #include "resources.h"
  #include "screenshot.h"
  #include "ui.h"
  #include "uifilereq.h"
  #include "uimenu.h"
  #include "util.h"
  #include "videoarch.h"
  
  
  static gfxoutputdrv_t *ffmpeg_drv = NULL;
  
  #define MAX_FORMATS 7
  #define MAX_CODECS 15
  
  static ui_menu_entry_t format_menu[MAX_FORMATS + 1];
  static ui_menu_entry_t video_codec_menu[MAX_CODECS + 1];
  static ui_menu_entry_t audio_codec_menu[MAX_CODECS + 1];
  
  UI_MENU_DEFINE_RADIO(FFMPEGVideoCodec)
  UI_MENU_DEFINE_RADIO(FFMPEGAudioCodec)
  
  UI_MENU_DEFINE_SLIDER(FFMPEGVideoBitrate, VICE_FFMPEG_VIDEO_RATE_MIN, VICE_FFMPEG_VIDEO_RATE_MIN)
  UI_MENU_DEFINE_SLIDER(FFMPEGAudioBitrate, VICE_FFMPEG_AUDIO_RATE_MIN, VICE_FFMPEG_AUDIO_RATE_MAX)
  
  static UI_MENU_CALLBACK(save_movie_callback)
  {
      char *name = NULL;
      int width;
      int height;
  
      if (activated) {
          if (!ffmpeg_drv) {
              ui_error("FFMPEG not available.");
              return NULL;
          }
          name = sdl_ui_file_selection_dialog("Choose movie file", FILEREQ_MODE_SAVE_FILE);
          if (name != NULL) {
              width = sdl_active_canvas->draw_buffer->draw_buffer_width;
              height = sdl_active_canvas->draw_buffer->draw_buffer_height;
              memcpy(sdl_active_canvas->draw_buffer->draw_buffer, sdl_ui_get_draw_buffer(), width * height);
              util_add_extension(&name, ffmpeg_drv->default_extension);
              if (screenshot_save("FFMPEG", name, sdl_active_canvas) < 0) {
                  ui_error("Cannot save movie.");
              }
              lib_free(name);
              return sdl_menu_text_exit_ui;
          }
      }
      return NULL;
  }
  
  ui_menu_entry_t ffmpeg_menu[] = {
      { "Format",
        MENU_ENTRY_DYNAMIC_SUBMENU,
        submenu_radio_callback,
        (ui_callback_data_t)format_menu },
      { "Video codec",
        MENU_ENTRY_DYNAMIC_SUBMENU,
        submenu_radio_callback,
        (ui_callback_data_t)video_codec_menu },
      { "Audio codec",
        MENU_ENTRY_DYNAMIC_SUBMENU,
        submenu_radio_callback,
        (ui_callback_data_t)audio_codec_menu },
      { "Video bitrate",
        MENU_ENTRY_RESOURCE_INT,
        slider_FFMPEGVideoBitrate_callback,
        (ui_callback_data_t)"Set video bitrate" },
      { "Audio bitrate",
        MENU_ENTRY_RESOURCE_INT,
        slider_FFMPEGAudioBitrate_callback,
        (ui_callback_data_t)"Set audio bitrate" },
      { "Save movie",
        MENU_ENTRY_DIALOG,
        save_movie_callback,
        NULL },
      SDL_MENU_LIST_END
  };
  
  static void update_codec_menus(const char *current_format)
  {
      int i;
      gfxoutputdrv_format_t *format;
      gfxoutputdrv_codec_t *codec;
  
      video_codec_menu[0].string = NULL;
      audio_codec_menu[0].string = NULL;
  
      if (!ffmpeg_drv) {
  #ifdef SDL_DEBUG
  fprintf(stderr, "%s: no driver found\n", __func__);
  #endif
          return;
      }
  
      /* Find currently selected format */
      format = ffmpeg_drv->formatlist;
  
      while (format) {
          if (!strcmp(format->name, current_format)) {
              break;
          } else {
              format++;
          }
      }
  
      if (!format) {
  #ifdef SDL_DEBUG
  fprintf(stderr, "%s: format %s not found\n", __func__, current_format ? current_format : "(NULL)");
  #endif
          return;
      }
  
      /* Update video codec menu */
      codec = format->video_codecs;
      i = 0;
  
      while (codec && codec->name) {
          video_codec_menu[i].string = (char *)(codec->name);
          video_codec_menu[i].type = MENU_ENTRY_RESOURCE_RADIO;
          video_codec_menu[i].callback = radio_FFMPEGVideoCodec_callback;
          video_codec_menu[i].data = int_to_void_ptr(codec->id);
  #ifdef SDL_DEBUG
  fprintf(stderr, "%s: video codec %i: %s (%i)\n", __func__, i, (codec->name) ? codec->name : "(NULL)", codec->id);
  #endif
  
          codec++;
          i++;
  
          if (i == MAX_CODECS) {
  #ifdef SDL_DEBUG
  fprintf(stderr, "%s: FIXME video codec %i > %i (MAX)\n", __func__, i, MAX_CODECS);
  #endif
              break;
          }
      }
      video_codec_menu[i].string = NULL;
  
      /* Update audio codec menu */
      codec = format->audio_codecs;
      i = 0;
  
      while (codec && codec->name) {
          audio_codec_menu[i].string = (char *)(codec->name);
          audio_codec_menu[i].type = MENU_ENTRY_RESOURCE_RADIO;
          audio_codec_menu[i].callback = radio_FFMPEGAudioCodec_callback;
          audio_codec_menu[i].data = int_to_void_ptr(codec->id);
  #ifdef SDL_DEBUG
  fprintf(stderr, "%s: audio codec %i: %s (%i)\n", __func__, i, (codec->name) ? codec->name : "(NULL)", codec->id);
  #endif
  
          codec++;
          i++;
  
          if (i == MAX_CODECS) {
  #ifdef SDL_DEBUG
  fprintf(stderr, "%s: FIXME audio codec %i > %i (MAX)\n", __func__, i, MAX_CODECS);
  #endif
              break;
          }
      }
      audio_codec_menu[i].string = NULL;
  }
  
  static UI_MENU_CALLBACK(custom_FFMPEGFormat_callback)
  {
      if (activated) {
          resources_set_string("FFMPEGFormat", (char *)param);
          update_codec_menus((const char *)param);
      } else {
          const char *w;
  
          resources_get_string("FFMPEGFormat", &w);
          if (!strcmp(w, (char *)param)) {
              return sdl_menu_text_tick;
          }
      }
      return NULL;
  }
  
  void sdl_menu_ffmpeg_init(void)
  {
      int i;
      gfxoutputdrv_format_t *format;
      const char *w;
  
      ffmpeg_drv = gfxoutput_get_driver("FFMPEG");
  
      if (!ffmpeg_drv) {
  #ifdef SDL_DEBUG
  fprintf(stderr, "%s: no driver found\n", __func__);
  #endif
          return;
      }
  
      format = ffmpeg_drv->formatlist;
      i = 0;
  
      do {
          format_menu[i].string = format->name;
          format_menu[i].type = MENU_ENTRY_RESOURCE_RADIO;
          format_menu[i].callback = custom_FFMPEGFormat_callback;
          format_menu[i].data = (ui_callback_data_t)(format->name);
  #ifdef SDL_DEBUG
  fprintf(stderr, "%s: format %i: %s\n", __func__, i, (format->name) ? format->name : "(NULL)");
  #endif
  
          format++;
          i++;
  
          if (i == MAX_FORMATS) {
  #ifdef SDL_DEBUG
  fprintf(stderr, "%s: FIXME format %i > %i (MAX)\n", __func__, i, MAX_FORMATS);
  #endif
              break;
          }
      } while (format->name);
  
      format_menu[i].string = NULL;
  
      resources_get_string("FFMPEGFormat", &w);
      update_codec_menus(w);
  }
  
  void sdl_menu_ffmpeg_shutdown(void)
  {
      if (screenshot_is_recording()) {
          screenshot_stop_recording();
      }
  }
  
  #endif /* HAVE_FFMPEG */
  