/* Darksnow - A GUI for darkice
 * Copyright (C) 2004-2005 Rafael Diniz <rafael@riseup.net>
 *
 * This source code is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Public License as published 
 * by the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 *
 * This source code 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.
 * Please refer to the GNU Public License for more details.
 *
 * You should have received a copy of the GNU Public License along with
 * this source code; if not, write to:
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libintl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <signal.h>

#ifndef __GLOBAL_H__
#include "global.h"
#endif

#ifndef __CONSTANTS_H__
#include "constants.h"
#endif

#ifndef __GTK_H__
#include <gtk/gtk.h>
#endif

#ifndef __CONFIG_FILES_H__
#include "config_files.h"
#endif

#ifndef __INTERFACE_H__
#include "interface.h"
#endif

#ifdef FUNNY
#define FUN 1
#else 
#define FUN 0
#endif

/* callback that start darkice */
void dark_start( GtkWidget *widget, gpointer data) {
  char *darkice_verbosity;
  char command[128], foo, dark_output[128];

  /* if the first caracter of shared area is 1, means that the streaming is running and we cannot start another darkice */
  sscanf((char *) shared_area, "%c", &foo);
  if (foo == '1')
    return;


  /* call the function that load the values from widgets and save to the darksnow config file */
  darksnow_config_store(1, NULL);
  /* call the function that translate the darksnow config file to the darkice config file */
  darksnow2darkice_cfg();

  darkice_verbosity =  (char *) gtk_entry_get_text  ( GTK_ENTRY(GTK_COMBO(combo_verbosity)->entry));

  strcpy(command,"darkice");
  strcat(command," -v ");
  strcat(command, darkice_verbosity);
  strcat(command," -c ");
  strcat(command, darkice_cfg);
  strcat(command," &> ");
  strcat(command, darksnow_temp);


  if ((pid = fork()) == -1) {
    printf("Fork error! God save the queen!\n");
    gtk_main_quit();
  }
  
  if (!pid) {
    /* streaming started */
    sprintf ((char *) shared_area, "11");
    system(command);
    /* if the system() returns, this means that the streaming stopped */
    sprintf ((char *) shared_area, "01");
    _exit(-1);
  }

  strcpy(dark_output, gettext("-->    Command     <--\n"));
  strcat(dark_output, command);
  strcat(dark_output, gettext("\n--> Darkice output <--\n") );

  gtk_text_buffer_set_text (buffer, dark_output , strlen(dark_output));
  
  /* print the darkice output for the first time */
  usleep(200000);
  text_box_loop (1); 
}

/* callback that stop darkice */
void dark_stop( GtkWidget *widget, gpointer data ){
  char out[32];

  system("killall darkice &> /dev/null");
  strcpy(out, gettext("Darkice off") );
  gtk_text_buffer_set_text (buffer, out, strlen(out));

}

void dark_put_in_box ( GtkWidget *widget, gpointer data ) {
  FILE *f_darksnow_cfg;
  char *darksnow_path;
  char foo[256] = {0};
  char server[256] = {0};
  char port[128] = {0};
  char mountpoint[128] = {0};
  char pass[128] = {0};
  char remotedump[256] = {0};
  char localdump[256] = {0};
  char adddate;
  char radioname[128] = {0};
  char description[256] = {0};
  char url[256] = {0};
  char genre[128] = {0};
  char icecast[128] = {0};
  char format[128] = {0};
  char bitrate[128] = {0};
  char bitratemode[128] = {0};
  char samplerate[128] = {0};
  char quality[128] = {0};
  char bitspersample[128] = {0};
  char channel[128] = {0};
  char buffersize[128] = {0};
  char device[128] = {0};
  char public[128] = {0};
  char verbosity[8] = {0};
  DIR *directory;

  darksnow_path = (char *) gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_open));
  
  if ( (directory = opendir(darksnow_path))) {
    printf("Error: %s is a directory\n", darksnow_path);
    closedir (directory);
    return;
  }

  if (!(f_darksnow_cfg = fopen(darksnow_path, "r"))) {
    printf("Error: Cannot open %s\n", darksnow_path);
    return;
  }
  
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, server);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, port);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, mountpoint);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, pass);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, radioname);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, description);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, url);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, genre);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, icecast);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, format);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, bitrate);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, bitratemode);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, samplerate);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, quality);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, bitspersample);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, channel);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, buffersize);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, device);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, public);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, verbosity);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, remotedump);
  fscanf(f_darksnow_cfg, "%[^=]=%[^\n]\n", foo, localdump);
  fscanf(f_darksnow_cfg, "%[^=]=%c\n", foo, &adddate);

  gtk_entry_set_text ( (GtkEntry *) entry_server, server);
  gtk_entry_set_text ( (GtkEntry *) entry_port, port);
  gtk_entry_set_text ( (GtkEntry *) entry_mountpoint, mountpoint);
  gtk_entry_set_text ( (GtkEntry *) entry_pass, pass);
  gtk_entry_set_text ( (GtkEntry *) entry_radioname, radioname);
  gtk_entry_set_text ( (GtkEntry *) entry_description, description);
  gtk_entry_set_text ( (GtkEntry *) entry_url, url);
  gtk_entry_set_text ( (GtkEntry *) entry_genre, genre);
  gtk_entry_set_text ( (GtkEntry *) entry_server, server);
  gtk_entry_set_text ( (GtkEntry *) entry_remotedump, remotedump);
  gtk_entry_set_text ( (GtkEntry *) entry_localdump, localdump);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_icecast)->entry), icecast);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_format)->entry), format);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_bitrate)->entry), bitrate);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_bitratemode)->entry), bitratemode);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_samplerate)->entry), samplerate);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_quality)->entry), quality);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_bitspersample)->entry), bitspersample);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_channel)->entry), channel);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_buffersize)->entry), buffersize);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_device)->entry), device);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_public)->entry), public);
  gtk_entry_set_text ( GTK_ENTRY(GTK_COMBO(combo_verbosity)->entry), verbosity);

  if (adddate == '1')
    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (checkbutton_adddate), TRUE);
  else
    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (checkbutton_adddate), FALSE);

  fclose(f_darksnow_cfg);

  gtk_widget_hide(file_open);
  
}

void dark_write_config ( GtkWidget *widget, gpointer data ) {
  char *darksnow_path;

  darksnow_path = (char *) gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_save));
  if (darksnow_config_store (0, darksnow_path))
    gtk_widget_hide(file_save);
  
}


void dark_about ( GtkWidget *widget, gpointer data ) {
  gtk_widget_show (dialog_about);
}


void dark_localdump (GtkWidget *widget, gpointer data){
  gtk_entry_set_text ( (GtkEntry *) entry_localdump, (char *) gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_localdump)) );
  gtk_widget_hide (file_localdump);

}

void clean_text_view_memory(){
  GtkTextIter start_iter, end_iter;

  gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
  gtk_text_iter_forward_lines (&start_iter, 6);
  gtk_text_iter_backward_lines (&end_iter, 6);
  gtk_text_buffer_delete(buffer, &start_iter, &end_iter);

}


gboolean status_loop (gboolean foo) {
  char status[3];
  static int alarm_id = 0;
  

  /** This checks if the status of the transmission if ON or OFF, using the shared area **/
  sscanf((char *) shared_area, "%s", status);

  /* if the update label flag is on */
  if (status[1] == '1') {
    /** streaming stopped **/
    if (status [0] == '0') {
      gtk_label_set_text(GTK_LABEL (label_status), gettext("Streaming Status: Stopped")); 
      text_box_loop(1);
      if (alarm_id)
	g_source_remove(alarm_id);
    }
    /** streaming started **/
    else {
      gtk_label_set_text(GTK_LABEL (label_status), gettext("Streaming Status: Started")); 
      text_box_loop(0);
      alarm_id = g_timeout_add (4000, (GSourceFunc) text_box_loop, 0);
    }

    strncpy((char *) shared_area+1, "0", 1);  
  }

  /* I need nothing from child, just do this to prevent <defunct> processes */
  waitpid(pid, NULL, WNOHANG);

  return TRUE;
}

#define BUFFER_SIZE 16384

gboolean text_box_loop (int option) {
  char dark_output[BUFFER_SIZE];
  char status[3];
  int i;
  static int bytes_written = 0;

  sscanf((char *) shared_area, "%s", status);
  
  if (status[0] == '1' || option == 1) {
    
    while ( (i = read (darkice_fd, dark_output, BUFFER_SIZE - 1))  && i > 0 ) {
      dark_output[i] = 0;
      gtk_text_buffer_insert_at_cursor (buffer, dark_output, strlen(dark_output));
      bytes_written = bytes_written + i;

      /* 32 * BUFFER_SIZE =  */
      if (bytes_written > 524288){
	clean_text_view_memory();
	bytes_written = 0;
      }
    }
  }
  return TRUE; 
} 

/* callback que chama a funcao de saida do programa, eh issu mermo, mata tudo mermaum!! */
gboolean delete_event(GtkWidget *widget, GdkEvent  *event, gpointer data) {

  system("killall darkice &> /dev/null");
  gtk_main_quit ();
  return FALSE;
}

/* callback that exit without killing darkice */
gboolean delete_event_nd (GtkWidget *widget, GdkEvent  *event, gpointer data) {
  char foo;

  sscanf((char *) shared_area, "%c", &foo);
  if (foo == '1')
    kill(pid,SIGTERM);

  gtk_main_quit ();
  return FALSE;
}

gboolean main_quit (GtkWidget *widget, GdkEvent  *event, gpointer data) {
  char status = '0';

  sscanf ((char *) shared_area, "%c", &status);

  /* if darkice is running, ask for killing it */
  if (status == '1') {
    gtk_widget_show (button_yes_darkkill);
    gtk_widget_show (button_no_darkkill);
    gtk_widget_show (label_darkkill);
    gtk_widget_show (dialog_darkkill);
  }
  else
    delete_event_nd(NULL, NULL, NULL);
  
  return FALSE;
      
}


/* function that is called when darkice is not found */
void darkice_not_found() {
  char bar[192];

  /* sets up the darkice not found dialog */
  if (!FUN)
    sprintf(bar, gettext("Darkice not found!\nDownload darkice at http://darkice.sf.net/"));
  else
    sprintf(bar, gettext("Don't you know you should have the fucking\ndarkice to run this shit!!\nGet it at http://darkice.sf.net/\n"));
  
  dialog_darkdep = gtk_dialog_new ();
  label_darkdep = gtk_label_new ( bar );
  button_darkdep = gtk_button_new_with_label ( gettext("Close"));
  gtk_window_set_title(GTK_WINDOW (dialog_darkdep), gettext("Error"));
  gtk_widget_set_size_request (GTK_WIDGET (dialog_darkdep), 350, 200); 
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_darkdep)->action_area), button_darkdep, TRUE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_darkdep)->vbox), label_darkdep, TRUE, TRUE, 0);
  
  g_signal_connect (G_OBJECT (dialog_darkdep), "delete_event",G_CALLBACK (delete_event), NULL);
  g_signal_connect (G_OBJECT (button_darkdep), "clicked",G_CALLBACK (delete_event), NULL);
  
  gtk_widget_show (button_darkdep);
  gtk_widget_show (label_darkdep);
  gtk_widget_show (dialog_darkdep);

  gtk_main ();

}

void dark_detail (GtkWidget *widget, gpointer data) {
  if (show_detail) {
    show_detail = 0;
    gtk_button_set_label (GTK_BUTTON(button_detail), gettext("Show Details"));
    gtk_widget_hide (scroll_text);
    gtk_widget_hide (text);
    gtk_window_resize (GTK_WINDOW(window), SIZE_X, SIZE_Y);
  }
  else{
    show_detail = 1;
    gtk_button_set_label (GTK_BUTTON(button_detail), gettext("Hide Details"));
    gtk_widget_show (text);
    gtk_widget_show (scroll_text);
    gtk_window_resize (GTK_WINDOW(window), SIZE_X, SIZE_Y+110);
  }
}
