as-salamu alaykom
On Fri, Oct 06, 2006 at 11:06:57PM +0200, Mohammed Sameer wrote:
> perldoc -f sprintf
jazak Allahu khairan...

Attached with this email is the new version of ireminder.
Now the -azan option accepts a play command instead of an audio file.
The command can take two parameters, the first will be the prayer name, 
the second will be the prayer time. Here's an example:

ireminder -azan "myazan_cmd -opt1 %s -opt2 %s"

So when ireminder runs that myazan_cmd, it will subsitute the first '%s' 
with prayer name & second '%s' with prayer time.
#!/usr/bin/perl

#---
# $Id: ireminder,v 1.5 2004/12/30 00:40:55 nadim Exp $
#
# ------------
# Description:
# ------------
#  Copyright (c) 2004, Arabeyes, Nadim Shaikli
#
#  This is a prayer (and other Islamic events) reminder program.
#  Its a wrapper that uses Arabeyes.org's ITL package (ipraytime
#  to be specific) to attain all its values.  The script is meant
#  to be light, simple and flexible.
#
#  Based on a concept/idea from
#  - Ahmed El-Mahmoudy (aelmahmoudy -at- users sf net)
#
# -----------------
# Revision Details:     (Updated by Revision Control System)
# -----------------
#  $Date: 2004/12/30 00:40:55 $
#  $Author: nadim $
#  $Revision: 1.5 $
#  $Source: /home/arabeyes/cvs/projects/itl/programs/itools/ireminder,v $
#
#  (www.arabeyes.org - under GPL license)
#---

# TODO:
# - have it fork in the background if a similar process doesn't already
#   exist else kill the other process post a confirm (optionally)
# - have it print to the console not stdout (optionally)
# - clean-up the sound/bell stuff
# - have it be able to play reminder and Azan sounds (optionally)
# - have it spawn a GUI reminder/now dialogs (optionally)

use Getopt::Long;

use FileHandle;
STDOUT->autoflush(1);

##
# Specify global variable values and init some Variables
$in_script      = $0;
$in_script      =~ s|^.*/([^/]*)|$1|;

##
# Find how many spaces the scripts name takes up (nicety)
$in_spaces      = $in_script;
$in_spaces      =~ s/\S/ /g;

$version        = " (v - %I%)";
$ID             = "[$in_script]";

# Process the command line
&get_args();

# Make it simple, does user need help ?
if ($opt{help}) { &help(); }

# Account for the various ways a user might enter a list
%opt            = %{&listify_input(\%opt, "skip")};
%opt            = %{&listify_input(\%opt, "reminder")};

# Account for various places the ipraytime binary could reside-in
@bin_paths      = ("/usr/bin/", "/usr/local/bin/", "");
foreach my $entry (@bin_paths)
{
    $bin_path = "${entry}ipraytime";
    if (-x $bin_path)
    {
        # OK, found something I can use
        last;
    }
}
$ipraytime      = $opt{ipraytime}       || $bin_path;

# Search for notify-send (aelmahmoudy):
foreach my $entry (@bin_paths)
{
    $bin_path = "${entry}notify-send";
    if (-x $bin_path)
    {
        # OK, found something I can use
        last;
    }
}
$notifysend = $bin_path;

# Set some default reminder settings
@reminders      = @{$opt{reminder}} ? @{$opt{reminder}} : (1, 5, 10, 20);

# Enumerate the events we'll track and report on
$DAY_TOT_SEC    = (24 * 60 * 60);
@EVENTS         = (qw/imsaak fajr shorooq zuhr asr maghrib isha/);

# Set some defaults
$doing_2moro    = 0;
$time_to_use    = time();

if (!-x $ipraytime)
{
    &usage(1, "$ID ERROR - can't find '$ipraytime' \n");
}

# Continuously cycle through
for (;;)
{
    # Get current start time
    $ref_time_used      = &get_time($time_to_use);
    %time_used          = %{$ref_time_used};

    # Specify date to get info on
    $date_to_use        = sprintf( "%d%02d%02d",
                                   $time_used{year},
                                   $time_used{month},
                                   $time_used{day} );

    # Run the actual program executable and process its output
    $ref_today_events   = &get_ipraytime($date_to_use);
    %today_events       = %{$ref_today_events};

    # Cycle through all the prayers (and events)
    for ($i = 0; $i <= $#EVENTS; $i++)
    {
        # Skip any events a user might have noted on the command-line
        if ( defined $opt{skip} )
        {
            foreach my $option (@{$opt{skip}})
            {
                # Make sure to make the compare case insensitive
                if ( uc($option) eq uc($EVENTS[$i]) )
                {
                    $skip_event = 1;
                    last;
                }
            }

            # If a skip-hit occured, cycle out of the for loop
            if ($skip_event)
            {
                $skip_event     = 0;
                next;
            }
        }

        # Determine current time's placement within event times
        $before_last    = ( ($time_used{hour} <
                             $today_events{$EVENTS[$#EVENTS]}{hour}) ||
                            (($time_used{hour} ==
                              $today_events{$EVENTS[$#EVENTS]}{hour}) &&
                             ($time_used{min} <
                              $today_events{$EVENTS[$#EVENTS]}{min})) );
        $after_current  = ( ($time_used{hour} >
                             $today_events{$EVENTS[$i]}{hour}) ||
                            (($time_used{hour} ==
                              $today_events{$EVENTS[$i]}{hour}) &&
                             ($time_used{min} >=
                              $today_events{$EVENTS[$i]}{min})) );

        # If we are dealing with next day (upon start), cycle through
        if (!$before_last && !$doing_2moro) { last; }

        # Skip the past while making sure we didn't go over
        if ($before_last && $after_current)
        {
            next;
        }
        else
        {
            # If I'm here, then its immaterial which day I'm dealing with
            $doing_2moro        = 0;

            # See how many seconds we have left till next prayer
            if ($before_last)
            {
                # Get time difference between prayer and wallclock time
                $sec_diff       = ( $today_events{$EVENTS[$i]}{tot_sec} -
                                    $time_used{tot_sec} );
            }
            else
            {
                # Dealing with next day prayer
                # - Get portion of day left in today + tomorrow's
                $sec_diff       = ( ($DAY_TOT_SEC - $time_used{tot_sec}) +
                                    $today_events{$EVENTS[$i]}{tot_sec} );
            }               

            # Account for the reminder time and the time delta seconds
            $sec_sleep  = ( $sec_diff - $time_used{sec} );

            # Tell user what to expect next
            $str        = "$ID NOTE - Next event '$EVENTS[$i]' is at ";
            $str        .= "$today_events{$EVENTS[$i]}";
            &display($str);

            # Sort numerically descending
            foreach $reminder (sort {$b <=> $a} @reminders)
            {
                $sec_reminder   = ( $reminder * 60 );
                if ($sec_sleep < $sec_reminder)
                {
                    next;
                }

                $sec_sleep      -= $sec_reminder;

                # Take a nap and wait :-)
                &do_reminder($EVENTS[$i],
                             $sec_sleep,
                             \%today_events,
                             $reminder);

                $sec_sleep      = $sec_reminder;
            }

            # Take a nap and wait (without reminders :-)
            &do_reminder($EVENTS[$i],
                         $sec_sleep,
                         0,
                         0);

            &do_alarm($EVENTS[$i], \%today_events);

            # Establish new time for next prayer
            # - This is opted for instead of accounting for passed sec's
            $ref_time_used      = &get_time(time());
            %time_used          = %{$ref_time_used};
        }
    }

    # Cycle through & advance calc 1 day forward (ie. look at next day)
    $time_to_use        = ( time() + $DAY_TOT_SEC );
    $doing_2moro        = 1;
}

       ###        ###
######## Procedures ########
       ###        ###

##
# Print on screen passed-in string
sub display
{
    my ($string)        = @_;

    # Do some clean-up and backtrack per use command-line directives
    if ($opt{inplace})
    {
        print "\r";
        print " " x 78;
        print "\r";
    }
    print $string;

    if (!$opt{inplace})
    {
        print "\n";
    }

                # (aelmahmoudy): also display message in X if possible
                if ( $ENV{DISPLAY} && (fork() == 0) && (-x $notifysend) )
                {
                        (my $dummy, $string) = split (/\]/, $string, 2);
                        my $i = index($string, "-");
                        $string = substr($string, $i + 1);
#                 exec ("wish << EOF
#wm title . ireminder
#label .l -text \"$string\"
#button .b -text OK -command exit
#pack .l .b
#EOF");
      exec ("$notifysend \"Praytime reminder\" \"$string\" ");
                }
                
}

##
# Adjust user input to end-up with a proper array
sub listify_input
{
    my ($ref_in_opt,
        $in_str)        = @_;

    my (
        %in_opt,
        @in_arr,
        @mod_arr,
       );

    %in_opt             = %{$ref_in_opt};
    @in_arr             = @{$in_opt{$in_str}};

    # Make sure to accept for instance,
    # 1. -skip one -skip two
    # 2. -skip "one two"
    # 3. -skip "one, two"
    foreach my $string (@in_arr)
    {
        if ($string =~ /\s+/)
        {
            my @sub_string      = split(/[,]*\s+/, $string);
            push (@mod_arr, @sub_string);
            next;
        }
        push (@mod_arr, $string);
    }

    $in_opt{$in_str}    = [EMAIL PROTECTED];
    return(\%in_opt);
}

##
# Populate time hash/struct using the passed-in time value
sub get_time
{
    my ($in_time)       = @_;

    my (
        %tm,
       );

    # seconds, minutes, hours, day, month, year, day.week, day.year, DST
    ($tm{sec},
     $tm{min},
     $tm{hour},
     $tm{day},
     $tm{month},
     $tm{year},
     $tm{dayofweek},
     $tm{dayofyear},
     $tm{dst})          = localtime($in_time);

    # Some reability corrections
    $tm{month}          = ($tm{month} + 1);
    $tm{year}           = (1900 + $tm{year});

    # Set some needed values
    $tm{tot_min}        = ($tm{min} + (60 * $tm{hour}));
    $tm{tot_sec}        = (60 * $tm{tot_min});

    return(\%tm);
}

##
# Populate event hash/struct based on ipraytime's output using date passed-in
sub get_ipraytime
{
    my ($in_date)       = @_;

    my (
        $aux,
        @out_ipray,
        $ipray,
        @times,
       );

    if (defined $in_date)
    {
        $aux    = "--date $in_date ";
    }

    @out_ipray  = `$ipraytime $aux`;

    #     Date         Fajr    Shorooq   Zuhr     Asr    Maghrib   Isha 
    #--------------------------------------------------------------------
    # [22-07-2004]     5:22     6:50    13:27    16:43    20:04    21:34
    #
    #Today's Imsaak    :   5:17

    foreach my $line (@out_ipray)
    {
        # Remove the carriage returns
        chomp($line);

        # Find the proper line to process
        if ($line =~ /\[\d+-\d+-\d+\]/)
        {
            @entries            = split (/\s\s+/, $line);
            $ipray{fajr}        = $entries[1];
            $ipray{shorooq}     = $entries[2];
            $ipray{zuhr}        = $entries[3];
            $ipray{asr}         = $entries[4];
            $ipray{maghrib}     = $entries[5];
            $ipray{isha}        = $entries[6];
        }

        # Grab today's imsaak time
        if ($line =~ /^Today.*Imsaak\s*:\s*(\d+:\d+)\s*/)
        {
            $ipray{imsaak}      = $1;
        }
    }

    # Get the total number of seconds for each prayer and event
    for (my $i = 0; $i <= $#EVENTS; $i++)
    {
        @times                          = split(/\:/, $ipray{$EVENTS[$i]});
        $ipray{$EVENTS[$i]}{hour}       = $times[0];
        $ipray{$EVENTS[$i]}{min}        = $times[1];
        $ipray{$EVENTS[$i]}{tot_min}    = ($ipray{$EVENTS[$i]}{min} +
                                           (60 * $ipray{$EVENTS[$i]}{hour}));
        $ipray{$EVENTS[$i]}{tot_sec}    = (60 * $ipray{$EVENTS[$i]}{tot_min});

    }

    # Return the newly populated hash/structure
    return (\%ipray);
}

##
# Trigger a reminder
sub do_reminder
{
    my ($in_name,
        $in_time,
        $ref_event_struct,
        $in_rem)                = @_;

    my (
        $name,
        $str,
       );

    %event_struct       = %{$ref_event_struct};
    $name               = ucfirst($in_name);

    # Take a nap and wait
    sleep($in_time);
    
    # See if a reminder note is warranted
    if ($in_rem > 0)
    {

      NAME_CASE:
        {
            if ($in_name eq "imsaak")
            {
                $str = "Fasting is to commence ($event_struct{$in_name})";
                last NAME_CASE;
            }
            if ($in_name eq "shorooq")
            {
                $str = "Salat Al-Fajr expires ($event_struct{$in_name})";
                last NAME_CASE;
            }
            #default
            $str = "Salat Al-$name ($event_struct{$in_name})";
        }

        &play_sound();
        &display("$ID REMINDER - $str in $in_rem minutes !!");
    }
}

##
# Trigger an alarm
sub do_alarm
{
    my ($in_name,
        $ref_event_struct)      = @_;

    my (
        $name,
        $event_struct,
        $num_rings,
        $str,
       );

    $name               = ucfirst($in_name);
    %event_struct       = %{$ref_event_struct};
    $num_rings          = 4;

  NAME_CASE:
    {
        if ($in_name eq "imsaak")
        {
            $str        = "to start your Fast";
            last NAME_CASE;
        }
        if ($in_name eq "shorooq")
        {
            $str        = "notes passing of Salat Al-Fajr";
            last NAME_CASE;
        }
        #default
        $str            = "for Salat Al-$name";
                if (defined $opt{azan}) { &play_azan($name, 
$event_struct{$in_name}); } # (aelmahmoudy): only at salat time
    }

    &display("$ID $event_struct{$in_name} - Time NOW $str !!");

    for(my $i = 0; $i < $num_rings; $i++)
    {
        &play_sound();
        sleep(1);
    }
}
##
# Play an azan file (aelmahmoudy)
sub play_azan
{
  my ($salat_name, $salat_time) = @_;
  my $playcmd = sprintf($opt{azan}, $salat_name, $salat_time) ||
                "mplayer -really-quiet -noconsolecontrols 
/usr/share/sounds/azan.wav";
  $playcmd = "$playcmd > /dev/null 2>&1";
        
        if(fork() == 0) { exec($playcmd); exit; }
}
##
# Play a sound file (if possible) else gimme a beep :-)
sub play_sound
{
    print "\a";
}

##
# Print short usage info
sub usage
{
    my ($die_after,
        $err_msg)       = @_;

    if (defined $err_msg) { print $err_msg; }
    print qq
|Usage: $in_script [-ipraytime path]
       $in_spaces [-skip event_name]
       $in_spaces [-reminder minutes]
       $in_spaces [-azan [audio_file]]
       $in_spaces [-inplace]
       $in_spaces [-help]
|;
    if ( $die_after ) { exit(5); }
}

##
# Print one-liner help
sub help
{
    &usage(0);

    print qq|
-> remind user visually and via audio of Islamic prayer times & misc events

  Options:

    [-ipraytime path]   : Specify the executable path to program
    [-skip event_name]  : Specify name of prayer/event to skip (list ok)
    [-reminder minutes] : Specify prior to how many minutes to remind (list ok)
    [-azan [command]]   : Specify a command to play azan, it can be supplied 
with
                          two parameters in the form of '%s', the first will be
                          prayer name, the second will be prayer time
    [-inplace]          : Specify to print output in-place (without scrolling)
    [-help]             : Produce this help screen

|;
    exit(10);
}

##
# Get the command line arguments
sub get_args
{
    &GetOptions(
                \%opt,          # Hash to store all input options in
                "ipraytime=s",  # specify the binary ipraytime executable
                "skip=s@",      # array'ed list of skip events
                "reminder=s@",  # array'ed list of reminder times (minutes)
                "azan:s", # (aelmahmoudy)
                "inplace",      # specify to print in-place outputs (no scroll)
                "help",         # print a brief help screen
                ) || ( $? = 257, &usage(1, "$ID ERROR - Invalid argument\n") );
}
_______________________________________________
Developer mailing list
[email protected]
http://lists.arabeyes.org/mailman/listinfo/developer

رد على