/*
 * This is xvmpeg v0.1a (4-08-1995)
 * Copyright (C) 1995 Alexandre Naaman <hoser@step.polymtl.ca>
 */

/*   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., 675 Mass Ave, Cambridge, MA 02139, USA. */


#include <xview/xview.h>
#include <xview/panel.h>
#include <xview/notice.h>
#include <xview/file_chsr.h>
#include <xview/icon.h>
#include <xview/svrimage.h>
#include "xvmpeg.h"

void show_warning(Panel_item parent)
{
  Xv_notice notice;
  
  notice = (Xv_notice)xv_create(parent, NOTICE,
  	NOTICE_MESSAGE_STRINGS,
  		"No file has been selected!",
  		"Use \"Open file...\" button to select file.",
  		NULL,
  	NOTICE_BUTTON_YES,	"Ok",
  	NOTICE_NO_BEEPING,	TRUE, 
  	XV_SHOW,		TRUE,
  	NULL);
  	
  xv_destroy_safe(notice);
}

void play_anim(Panel_item item)
{
  char command[PATH_MAX+NAME_MAX+50];
  char dithering[30];
  int  i,quiet=0, dec, dith;
  Panel panel;
  Panel_item options, dither;
  char *f_name;
  
  options=(Panel_item)xv_get(item, XV_KEY_DATA, OPTIONS_KEY);
  dither=(Panel_item)xv_get(item, XV_KEY_DATA, DITHER_KEY);
  panel=(Panel)xv_get(item, XV_KEY_DATA, PANEL_KEY);
  f_name=(char *)xv_get(item, XV_KEY_DATA, F_NAME_KEY); 
   
  dec=(int)xv_get(options,PANEL_VALUE);
  dith=(int)xv_get(dither,PANEL_VALUE);

  /* Show a warning if no file has been selected -- nothing to play */
  if (f_name[0]=='\0') {
  	show_warning(panel);
  	return;
  }

  /* Determine which options have been chosen */
  strcpy(command,"mpeg_play ");
  for(i=0;dec;i++,dec>>=1)
    if (dec & 1) 
      switch(i) {
        case 0: strcat(command," -nob"); break;
        case 1: strcat(command," -nop"); break;
        case 2: break;
        case 3: strcat(command," -quiet"); 
        	quiet=1;
        	break;
        default: break;
      }
    else if (i==2) strcat(command," -shmem_off"); 
  
  /* Determine which type of dithering has been chosen */
  switch(dith){
  	case 0: strcpy(dithering," -dither ordered"); break;
  	case 1: /* strcpy(dithering," -dither ordered2"); */ break;
  	case 2: strcpy(dithering," -dither mbordered"); break;
  	case 3: strcpy(dithering," -dither fs4"); break;
  	case 4: strcpy(dithering," -dither fs2"); break;
  	case 5: strcpy(dithering," -dither fs2fast"); break;
  	case 6: strcpy(dithering," -dither hybrid"); break;
  	case 7: strcpy(dithering," -dither hybrid2"); break;
  	case 8: strcpy(dithering," -dither 2x2"); break;
  	case 9: strcpy(dithering," -dither gray"); break;
  	case 10:strcpy(dithering," -dither color"); break;
  	case 11:strcpy(dithering," -dither none"); break;
  	case 12:strcpy(dithering," -dither mono"); break;
  	case 13:strcpy(dithering," -dither threshold"); break;
  	default: break;
  }
  if (dith!=1) strcat(command,dithering);

  strcat(command," ");
  strcat(command,f_name); 
  if(quiet) 
    strcat(command," >/dev/null");
  else
    strcat(command," >/dev/console");
  strcat(command," 2>/dev/console &");

#ifdef DEBUG
  fprintf(stderr,command);  
#endif  
  /* Execute system command! */
  system(command);
}


void opened_file(File_chooser fc,char *path,char *file,Xv_opaque client_data)
{
  char title[NAME_MAX+10]="xvmpeg: ";
  char *f_name=(char *)xv_get(fc, XV_KEY_DATA, F_NAME_KEY);
  Frame frame=(Frame)xv_get(fc,XV_KEY_DATA, FRAME_KEY);

  strcat(title,file);
  strcpy(f_name,path);
  xv_set(frame,FRAME_LABEL,title,NULL);
  xv_set(fc, XV_SHOW, FALSE, NULL);	
}

void open_file(Panel_item item)
{
  File_chooser	open_file_win;
  char *f_name=(char *)xv_get(item, XV_KEY_DATA, F_NAME_KEY);
  Frame frame=(Frame)xv_get(item, XV_KEY_DATA, FRAME_KEY);
  static time_t time1, time2;
  
  time(&time2);
  
  /* If two seconds have not elapsed since the last "Open file" window
   * was opened, do not open another one.
   */
  if(difftime(time2,time1) > 2.0) {
    open_file_win = xv_create(frame, FILE_CHOOSER_OPEN_DIALOG,
    	XV_LABEL,			"Select file to load",
  	FILE_CHOOSER_NOTIFY_FUNC,	opened_file,
  	XV_KEY_DATA,			FRAME_KEY, frame,
  	XV_KEY_DATA,			F_NAME_KEY, (char *)f_name,
  	NULL); 	
  
    xv_set(open_file_win, XV_SHOW, TRUE, NULL);	 
  }
  time(&time1);
}

void setup_icon(Frame frame)
{
  Server_image image_ok, image_mask;
  Icon icon;

  image_ok = (Server_image)xv_create(XV_NULL, SERVER_IMAGE,
  	XV_WIDTH,    xvmpeg_width,
  	XV_HEIGHT,   xvmpeg_height,
  	SERVER_IMAGE_DEPTH,  1,
  	SERVER_IMAGE_X_BITS, xvmpeg_bits,
        NULL);
  image_mask = (Server_image)xv_create(XV_NULL, SERVER_IMAGE,
  	XV_WIDTH,    xvmpeg_width,
  	XV_HEIGHT,   xvmpeg_height,
  	SERVER_IMAGE_DEPTH,  1,
  	SERVER_IMAGE_X_BITS, xvmpeg_mask_bits,
  	NULL);
  icon = (Icon)xv_create(frame, ICON,
  	ICON_IMAGE,       image_ok,
  	ICON_MASK_IMAGE,  image_mask,
  	ICON_LABEL,       "xvmpeg", 
  	NULL);
  xv_set(frame, FRAME_ICON, icon, NULL);
}

void about_xvmpeg(Panel_item parent)
{
  Xv_notice notice;

  notice = (Xv_notice)xv_create(parent, NOTICE,
  	NOTICE_MESSAGE_STRINGS,
  		"xvmpeg 0.1a, Copyright (C) 1995 Alexandre Naaman",
  		"<hoser@step.polymtl.ca>",
  		"-------------------------------------------------",
  		"xvmpeg comes with ABSOLUTELY NO WARRANTY. This is",
  		"free software, you are welcome to redistribute it",
  		"under certain conditions; See the GNU General",
  		"Public License for details.",
  		NULL,
  	NOTICE_BUTTON_YES,	"Ok",
  	NOTICE_NO_BEEPING,	TRUE,
  	XV_SHOW,		TRUE,
  	NULL);

  xv_destroy_safe(notice); 
}

void process_args(int argc,char *argv[],Frame frame,char *f_name)
{
  struct stat statbuf;
  char temp[PATH_MAX+NAME_MAX];
  
  if(argc>1) {
    if(stat(argv[1], &statbuf)<0)
      fprintf (stderr,"Unable to stat %s\n",argv[1]);
    else if ( (statbuf.st_mode & S_IFMT) != S_IFDIR &&
              (statbuf.st_mode & S_IFMT) == S_IFREG ) {
      strcpy(f_name,argv[1]);
      sprintf(temp,"xvmpeg: %s", f_name);
      xv_set(frame,FRAME_LABEL,temp,NULL);
    } else fprintf(stderr,
    	"xvmpeg: %s is a directory or is not a regular file.\n",argv[1]);
  }
}

void window_resize(Frame parent)
{
  int height=(int)xv_get(parent,XV_KEY_DATA,INIT_HEIGHT_KEY);
  int width=(int)xv_get(parent,XV_KEY_DATA,INIT_WIDTH_KEY);

  /* This simply sets the base frame's size back to it's initial size.
   * I _think_ that xview is smart enogh not to change the dimensions
   * of the window if they have not changed.
   */
  if(height)  xv_set(parent,XV_HEIGHT,height);
  if(width) xv_set(parent,XV_WIDTH,width); 
}

void quit_xvmpeg(Frame frame)
{
  xv_destroy_safe(frame);
  exit(0);
}

void event_proc(Panel panel,Event *event)
{
  /* This event procedure takes care of keyboard accelerators */
  
  Panel_item options, dither;
  Frame frame;
  char *f_name;
  static time_t time1, time2;

  options=(Panel_item)xv_get(panel, XV_KEY_DATA, OPTIONS_KEY);
  dither=(Panel_item)xv_get(panel, XV_KEY_DATA, DITHER_KEY);
  panel=(Panel)xv_get(panel, XV_KEY_DATA, PANEL_KEY);
  f_name=(char *)xv_get(panel, XV_KEY_DATA, F_NAME_KEY); 
  frame=(Frame)xv_get(panel, XV_KEY_DATA, FRAME_KEY);
  
  if(event_is_ascii(event)) {
#ifdef DEBUG
    printf("Key= %c\n",event_action(event));
#endif
    switch(toupper(event_action(event))) {
      case 'O': xv_set(panel,
      			XV_KEY_DATA, FRAME_KEY, frame,
      			XV_KEY_DATA, F_NAME_KEY, (char *)f_name,
      			NULL);
      		open_file(panel); break;
      case 'P': time(&time2);
      		/* Let's make sure that there is a delay of
      		 * at least two seconds between keypresses.
      		 */
  		if(difftime(time2,time1) > 2.0) {
       		  xv_set(panel,
      			XV_KEY_DATA, OPTIONS_KEY, options,
      			XV_KEY_DATA, DITHER_KEY, dither,
      			XV_KEY_DATA, PANEL_KEY, panel,
      			XV_KEY_DATA, F_NAME_KEY, f_name,
      			NULL);
      		  play_anim(panel); 
      		}
      		time(&time1);
      		break;
      case 'A': about_xvmpeg(panel); break;
      case 'Q': quit_xvmpeg(frame); break;
      default:  break;
    }
  }
}

void show_about_xvmpeg(Panel_item item)
{
  Panel parent=(Panel)xv_get(item,PANEL_CLIENT_DATA);

  about_xvmpeg(parent);
}

int main(int argc,char *argv[])
{
  Main_win mw;
  
  xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);

  mw.frame = (Frame)xv_create(XV_NULL, FRAME,
  	 FRAME_LABEL, XVMPEG_NAME,
  	 FRAME_SHOW_RESIZE_CORNER, FALSE, 
  	 NULL);

  /* Take care of window resizing events with window managers other
   * than ol(v)wm.
   */       
  xv_set(mw.frame,
  	WIN_EVENT_PROC, window_resize,
  	NULL); 

  /* Figure out what to do with command line arguments */
  process_args(argc,argv,mw.frame,mw.f_name);

  /* Time to create the UI */
  mw.panel = (Panel)xv_create(mw.frame, PANEL, 
  	XV_HELP_DATA,		"xvmpeg:Panel",
  	PANEL_ACCEPT_KEYSTROKE, TRUE,
  	PANEL_BACKGROUND_PROC, event_proc, 
  	NULL);

  mw.open=xv_create(mw.panel, PANEL_BUTTON,
  	PANEL_NOTIFY_PROC,    open_file,
	PANEL_LABEL_STRING,   "Open file...",
	XV_HELP_DATA,	      "xvmpeg:Open_file",
	XV_KEY_DATA,	      F_NAME_KEY, (char *)mw.f_name,
	XV_KEY_DATA,	      FRAME_KEY, mw.frame,
	NULL);

  mw.anim=xv_create(mw.panel, PANEL_BUTTON,
	PANEL_NOTIFY_PROC,    play_anim,
	PANEL_LABEL_STRING,   "Play animation",
	XV_HELP_DATA,	      "xvmpeg:Play",
	NULL);

  mw.about=xv_create(mw.panel, PANEL_BUTTON,
  	PANEL_NOTIFY_PROC,	show_about_xvmpeg,
  	PANEL_LABEL_STRING,	"About",
  	PANEL_CLIENT_DATA,	mw.panel,  
  	XV_HELP_DATA,		"xvmpeg:About",
  	NULL);

  mw.options=xv_create(mw.panel, PANEL_CHECK_BOX,
	PANEL_NEXT_ROW,	      -1,
	PANEL_CHOICE_STRINGS, "No B Frames",
	                      "No P Frames",
	                      "Shared Mem.",
	                      "Quiet",
	                       NULL,
	PANEL_VALUE,	      12, /* Quiet and Shared Mem on by default */
	XV_HELP_DATA,	      "xvmpeg:Options",
	NULL);

  mw.dither=xv_create(mw.panel, PANEL_CHOICE_STACK,
	PANEL_LAYOUT,         PANEL_VERTICAL,
	PANEL_NEXT_ROW,	      -1,
	PANEL_LABEL_STRING,   "Dithering...",
	PANEL_CHOICE_STRINGS, "Ordered",
	                      "Fast Ordered",
	                      "Macroblock Ordered",
	                      "Floyd-Steinberg with 4 error values",
	                      "Floyd-Steinberg with 2 error values",
	                      "Fast Floyd-Steinberg with 2 error values",
	                      "Hybrid",
	                      "Hybrid with error propagation",
	                      "2x2",
	                      "Grayscale",
	                      "Colour 24 bit only",
	                      "No diplay, no dither",
	                      "Monochrome",
	                      "floyd-Steinberg simple, monochrome only",
	                      NULL,
	PANEL_VALUE,          1, /* Let fast ordered be the default */
	XV_HELP_DATA,	      "xvmpeg:Dithering",
	NULL);
  
  setup_icon(mw.frame);
  
  window_fit(mw.panel);
  window_fit(mw.frame);
  
  /* Get the size of the window */
  mw.init_height=(int)xv_get(mw.frame,XV_HEIGHT);
  mw.init_width=(int)xv_get(mw.frame,XV_WIDTH);

  /* Bind data to keys _AFTER_ the objects have been created. */
  xv_set(mw.anim,  
	XV_KEY_DATA,	OPTIONS_KEY, mw.options,
	XV_KEY_DATA,	DITHER_KEY, mw.dither,
	XV_KEY_DATA,	PANEL_KEY, mw.panel,
	XV_KEY_DATA,	F_NAME_KEY, (char *)mw.f_name,
  	NULL);

  xv_set(mw.frame,
  	XV_KEY_DATA,	INIT_HEIGHT_KEY, mw.init_height,
  	XV_KEY_DATA,	INIT_WIDTH_KEY, mw.init_width,
 	NULL);  
 	
  xv_set(mw.panel,
  	XV_KEY_DATA,	OPTIONS_KEY, mw.options,
	XV_KEY_DATA,	DITHER_KEY, mw.dither,
	XV_KEY_DATA,	PANEL_KEY, mw.panel,
	XV_KEY_DATA,	F_NAME_KEY, (char *)mw.f_name,
	XV_KEY_DATA,	FRAME_KEY, mw.frame,
  	NULL);
  	
  xv_main_loop(mw.frame);
  
  return 0;  
}