
/*
 adjust_volume
 Copyright (c) 2010 Nebil Reyhani

 This file is part of adjust_volume.
 adjust_volume 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 3 of the License, or
 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, see <http://www.gnu.org/licenses/>.

 Send your feedback or comments to: nebil.reyhani@gmail.com
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <gtk/gtk.h>

#define FONT "SANS normal 32"

char text1[32];
char text2[32];
static int step_counter=0;
static int volume_level=0;
static time_t g_time=0;
int fd_fifo;
FILE *p;

gboolean delayed_exit()
{
   unlink("/tmp/fifodnb01");
   gtk_main_quit();
   return FALSE;
}

gboolean refresh_text(GtkWidget *widget)
{
char str_buf[120];
char str_vol[80];
time_t l_time=0;
char c;
int j, k;

   time(&l_time);

   if(g_time!=0 && l_time-g_time>4)
   {
      close(fd_fifo);
      delayed_exit();
   }

   if(step_counter>25)
      step_counter=25;
   if(step_counter<0)
      step_counter=0;

   read(fd_fifo, str_buf, sizeof(str_buf));

   if(strcmp(str_buf, "UP")==0)
   {
      system("aumix -v +4");
      step_counter++;
      time(&g_time);
   }
   else if(strcmp(str_buf, "DOWN")==0)
   {
      system("aumix -v -4");
      step_counter--;
      time(&g_time);
   }
   else if(step_counter==0 && volume_level==0)
   {
      p=popen("aumix -q", "r");
      j=0;
      while((c=fgetc(p))!=EOF)
         str_buf[j++]=c;
      str_buf[j]='\0';
      pclose(p);
      if(strncmp(str_buf, "vol", 3)<0)
      {
         printf("aumix is not found...\n");
         close(fd_fifo);
         delayed_exit();
      }
      k=0;
      for(j=0; j<9; j++)
      {
         if(str_buf[j]==',')
            break;
         if(j>3)
            str_vol[k++]=str_buf[j];
      }
      str_vol[k]='\0';

      volume_level=atoi(str_vol);
      step_counter=(volume_level*25)/100;
   }
   else
   {
      return TRUE;
   }

   str_buf[0]='\0';

   for(j=0; j<step_counter; j++)
      text1[j]='|';

   text1[j]='\0';

   for(j=25-step_counter; j>=0; j--)
      text2[j]='|';

   text2[25-step_counter]='\0';

   gdk_window_invalidate_rect(widget->window, NULL, TRUE);

   return TRUE;
}

static gboolean text_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
PangoLayout *layout;
PangoRenderer *renderer;
PangoContext *context;
PangoFontDescription *desc;
char markedup_text[320];

   /* Get the default renderer for the screen, and set it up for drawing  */
   renderer = gdk_pango_renderer_get_default (gtk_widget_get_screen (widget));
   gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), widget->window);
   gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), widget->style->black_gc);

   /* Create a PangoLayout, set the font and text */
   context = gtk_widget_create_pango_context (widget);
   layout = pango_layout_new (context);

   sprintf(markedup_text, "<span foreground='yellow' background='#FF3333'>%s</span><span foreground='#FFFFCC' background='#66CCCC'>%s</span>", text1, text2);

   pango_layout_set_markup (layout, markedup_text, -1);
   pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
   desc = pango_font_description_from_string (FONT);
   pango_layout_set_font_description (layout, desc);
   pango_font_description_free (desc);


   pango_renderer_draw_layout (renderer, layout, 0, 0);

   /* Clean up default renderer, since it is shared */
   gdk_pango_renderer_set_override_color (GDK_PANGO_RENDERER (renderer),
					 PANGO_RENDER_PART_FOREGROUND, NULL);
   gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), NULL);
   gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), NULL);

   /* free the objects we created */
   g_object_unref (layout);
   g_object_unref (context);

   return FALSE;
}

void get_layout_size(GtkWidget *widget, char *str, int *width, int *height)
{
PangoLayout *layout;
PangoContext *context;
PangoFontDescription *desc; 

   context = gtk_widget_create_pango_context (widget);
   layout = pango_layout_new (context);
   pango_layout_set_text (layout, str, -1);
   desc = pango_font_description_from_string (FONT);
   pango_layout_set_font_description (layout, desc);
   pango_font_description_free (desc);
   pango_layout_get_size (layout, width, height);
   return;
}

void snd_msg(char *str_msg)
{
   char msg_buf[120];

   if((fd_fifo=open("/tmp/fifodnb01", O_WRONLY)) == - 1)
   {
      fprintf(stderr, "Can't open the fifo.....\n");
      return;
   }

   sprintf(msg_buf, "%s", str_msg);

   write(fd_fifo, msg_buf, sizeof(msg_buf));

   close(fd_fifo);

   return;
}

int main(int argc, char* argv[])
{
GdkScreen *screen;
static GtkWidget *window = NULL;
GtkWidget *drawing_area;
int screen_width;
int screen_height;
int layout_width;
int layout_height;
struct stat attribut;


   if(argc<2) /* We need 'UP' or 'DOWN' as argument. If there is no argument exit */
   {
      printf("\nUsage:\t%s UP\n\t%s DOWN\n\nIncrease or decrease Master Volume displaying volume level on screen.\nThis application is supposed to be used with a keyboard shortcut.\nAumix (a command line mixer) is required.\n\n", argv[0], argv[0]);
      return 0;
   }

   stat("/tmp/fifodnb01", &attribut); /* Look if there is already a fifo */

   /* If there is a fifo, there must be another instant waiting for a message, */
   /* send it and exit */
   if(S_ISFIFO(attribut.st_mode)) 
   {
      snd_msg(argv[1]);
      return 0;
   }

   if(mkfifo("/tmp/fifodnb01", S_IWUSR | S_IRUSR |
    S_IRGRP | S_IROTH | S_IWOTH)<0)
   {
      fprintf(stderr, "Sorry! Can't create fifo file...\n");
      return 0;
   }

   if((fd_fifo=open("/tmp/fifodnb01", O_RDONLY | O_NONBLOCK)) == -1)
   {
      fprintf(stderr, "Can't open the fifo for read access...\n");
      return 0;
   }

   time(&g_time);

   gtk_init(&argc, &argv);

   if (!window)
   {
      window = gtk_window_new (GTK_WINDOW_POPUP);
      gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (window));
      gtk_window_set_title (GTK_WINDOW (window), "You shouldn't see this!");

      g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window);

      drawing_area = gtk_drawing_area_new ();
      gtk_container_add (GTK_CONTAINER (window), drawing_area);

      g_signal_connect (drawing_area, "expose-event",
			G_CALLBACK (text_expose_event), NULL);

      get_layout_size(drawing_area, "|||||||||||||||||||||||||", &layout_width, &layout_height);

      screen=gdk_screen_get_default();
      screen_width=gdk_screen_get_width(screen);
      screen_height=gdk_screen_get_height(screen);

      gtk_window_move(GTK_WINDOW(window),(screen_width-8)-(layout_width/PANGO_SCALE), (screen_height-8)-(layout_height/PANGO_SCALE));

      gtk_window_set_default_size (GTK_WINDOW (window), layout_width/PANGO_SCALE, layout_height/PANGO_SCALE);
    }

   if (!GTK_WIDGET_VISIBLE (window))
   {
      gtk_widget_show_all (window);
   }
   else
   {
      gtk_widget_destroy (window);
      window = NULL;
   }

   g_timeout_add(50, (GSourceFunc)refresh_text, drawing_area);

   gtk_main();

   unlink("/tmp/fifodnb01");

   return 0;
 }


