Finally I have my own domain name and my blog on my very own domain. I have now migrated my htpp://applegrew.blogspot.com to here.
Welcome home. 🙂
Finally I have my own domain name and my blog on my very own domain. I have now migrated my htpp://applegrew.blogspot.com to here.
Welcome home. 🙂
The open source project DC client framework jDCBot (http://jdcbot.sourceforge.net) I have been working on is now nearing its 1.0 milestone. Version 1.0 means that it will have all the required features that a DC client framework should have, like – managing shared files, hashing them, creating file lists, queuing downloads and resuming them when the source is available, multi-source downloading, etc.
This framework has been created from scratch, so unlike other DC clients which share DC++‘s code for the core functionality and hence provide similar features, jDCBot will provided unorthodox features. For example DC++ clients and its derivatives allow users only to provide different user names and passwords for different hubs. jDCBot on the other hand allows you to be passive or active in different hubs. So you can be passive and active both at the same time. This is useful in situations when say you are inside your college LAN and you want to connect to hubs inside the LAN and outside on the Internet too. In this case DC++ and derivatives will force you to be passive, but in jDCBot you can be active for inside your LAN and passive for outside the LAN. Well, you also get to set different descriptions, email addresses and connection types too.
There some other cool features too which are not present in other clients like allowing you to set different upload speeds for different users (this way you can give your friends a boost), blocking upload to particular users (could be misused but we are giving the power and it is upto the clients who will use jDCBot to make the decisions), using the virtual file list concept which allows the users to organize their share into virtual directories without actually reorganizing the files, the file names in file list can even be different from the original allowing the user to rename the file in the file list without rehashing or allowing the user to re-associate the virtual file with the actual file after the original file name/path changes so that rehashing is not required, and many more. Last but not the least it is pure JAVA framework and hence is platform independent and is very modular.
I recentry created the brand new site for jDCBot (http://jdcbot.sourceforge.net ). For the Javadoc section I wanted the Javadoc to match the site’s red and black theme. Below is its screenshot. Click on it for a better view, or even better visit jDCBot’s site (link is above) and goto to the Javadoc section.
Well anyway, below is the script.
The code
License: GNU Public License version 3.
/* Javadoc style sheet theme - Red N Black - by Nirupam Biswas (AppleGrew)*/ /* Define colors, fonts and other style attributes here to override the defaults */ /* Page background color */ body { background-color: #FFFFFF; color:#000000 } /* Headings */ h1, h2, h3 { font-family: Arial, Helvetica, sans-serif; color: #555555; } h1 {font-size: 145%;} a:link { line-height: 14px; font-weight: bold; text-decoration: none; color: #444444; } a:visited { color: #777777; text-decoration: none; font-weight: bold; } a:hover { border-bottom: 2px solid #666666; } hr{ color: #666666; background-color: #666666; text-align: left; border: 0; text-align: left;/*this will align it for IE*/ margin-left: 0; /*this will align it left for Mozilla*/ } /* Table colors */ .TableHeadingColor { background-image:url(javadoc.jpg); background-repeat:repeat-x; color:#FFFFFF;} .TableHeadingColor a:link, .TableHeadingColor a:visited { color: #bbbbbb; } .TableHeadingColor a:hover { border: none; background-color:#666666; } .TableSubHeadingColor { background: #EEEEEE; color:#000000 } .TableRowColor { background: #FFFFFF; color:#000000 } /* Font used in left-hand frame lists */ .FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 } .FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } .FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } /* Navigation bar fonts and colors */ .NavBarCell1 { background-image:url(javadoc.jpg);} .NavBarCell1 a:hover { border: none; background-color:#666666; } .NavBarCell1Rev { background-color:#666666; color:#FFFFFF} .NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;} .NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;} .NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} .NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000}
Also please save the following image and save it in the same directory with the style sheet above.
I love Linux. Why? Because it has so many cool cool cool … commands like grep, sed, find, etc. Of all the commands, I use grep the most. If grep is taken out of Linux then I will be severely crippled. Almost everyday I need to use it.
I will give you a recent case where I fixed a bug in LinuxDCpp in just 15 mins even when I had never looked into its code before and I had absolutely no experience building GUI applications in C++ or using GTK libraries.
I am using LinuxDCpp 1.0.1 which has a problem of not beeping when private messages are received even when I have configured it to do so. Because of this I had to repeatedly open the window of LinuxDCpp to check for new private messages. Then, one fine day I decided to fix this. The only problem was how and where. To answer my these questions I needed a starting point to start searching from. I had an idea; I realized that the best place to start searching from is the text – “Beep every time a private message is received“, this is the text that is displayed in the Preferences dialog of LinuxDCpp. I then un-tared the the source code of LinuxDCpp and opened the console in that directory, then I ran the command
$ grep -Rl "Beep every time a private message is received" .
Which yielded the result
./glade/settingsdialog.glade
I then opened that file and located the message. The code there read as following.
<child> <widget class="GtkCheckButton" id="soundPMReceivedCheckButton"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="label" translatable="yes"> Beep every time a private message is received</property> <property name="use_underline">True</property> <property name="draw_indicator">True</property> </widget> <packing> <property name="expand">False</property> <property name="fill">False</property> </packing> </child>
From my experience of HTML and common sense, I knew that soundPMReceivedCheckButton is the text that need to search for next. Hence I ran the command
$ grep -Rl "soundPMReceivedCheckButton" .
Which yielded the output
./linux/settingsdialog.cc
./glade/settingsdialog.glade
The second line was expected, but the first line contained the destination I must head to next. The code in that file read
// Sounds
sm->set(SettingsManager::PRIVATE_MESSAGE_BEEP, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(getWidget(
"soundPMReceivedCheckButton"))));
sm->set(SettingsManager::PRIVATE_MESSAGE_BEEP_OPEN, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
getWidget("soundPMWindowCheckButton"))));
From here on knowledge of C++ was required, but still grep was helpful. The lines spoke to me that there is a an object ‘sm’ which has a method ‘set’ which allows to set the properties of the program. PRIVATE_MESSAGE_BEEP is a constant which means that LinuxDCpp must beep on receiving the private message. From common sense, I concluded that the part of the program which actually generated the beep too must check for whether the property is SettingsManager::PRIVATE_MESSAGE_BEEP or not; in other words, that part of the program too must have the text PRIVATE_MESSAGE_BEEP. Hence my next command
$ grep -Rl "PRIVATE_MESSAGE_BEEP" .
I got the following outputs.
./client/SettingsManager.cpp
./client/SettingsManager.h
./linux/settingsdialog.cc
./linux/privatemessage.cc
As we already have seen the definition SettingsManager::PRIVATE_MESSAGE_BEEP, which clearly meant that PRIVATE_MESSAGE_BEEP must have been defined in the file SettingsManager.h. The only interesting result among them is privatemessage.cc. There I at last found what I was looking for. The code read
if (BOOLSETTING(PRIVATE_MESSAGE_BEEP_OPEN))
gdk_beep();
In that very file the searched for gdk_beep() which took me to the code
if ((state & GDK_WINDOW_STATE_ICONIFIED) || mw->currentPage_gui() != getContainer())
gdk_beep();
This is the code which was actually triggered on receiving private message and the code above that is activated when the private message window is opened.
The clear culprit was gdk_beep(). From Goggling out I found that it is part of GTK/GDK library and it is supposed to produce a beep from the internal speaker of the computer, but as per the many posts I saw on the various forums, it usually didn’t work. The only solution was to replace that with some other code. The easiest I could think of was using an external command to play a sound file. I opted for aplay which is usually installed on all current Linux computers. Also, I coded it such that user can configure LinuxDCpp to use any other commands by setting LINUX_DCPP_SND environment variable to the command to execute on receiving private message. For that I replaced
if (BOOLSETTING(PRIVATE_MESSAGE_BEEP_OPEN))
gdk_beep();
with
if (BOOLSETTING(PRIVATE_MESSAGE_BEEP_OPEN))
{
//Added by AppleGrew
const char *sndCmd = getenv("LINUX_DCPP_SND");
if(!sndCmd) {
string cmd = "aplay \"/usr/local/linuxdcpp/ping.wav\"";
system(cmd.data());
}else{
system(sndCmd);
}
I then edited the SConstruct file to automate the copying of the ping.wav file. For that added th following codes.
snd_file = ['ping.wav']
env.Alias('install', env.Install(dir = env['FAKE_ROOT'] + env['PREFIX'] + '/share/linuxdcpp', source = snd_file))
But, there was still a big problem. The SConstruct allowed the user to install it in /usr directory (the default is /usr/local). That meant I somehow needed to find out during runtime the location of the files. LinuxDCpp was already able to locate its pixmap (graphics) files, which are stored in the location – prefix_loc/pixmaps (prefix_loc is either /usr or /usr/local), I just needed to locate that code. It was clear that whatever mechanism LinuxDCpp was using, it will undoubtedly return the location /usr or /usr/local, and hence the code that accessed the pixmap files then would have to create the pixmap location as
string pixmap_location = function_or_method_that_gives_the_prefix_location + "/pixmaps"
Hence I ‘grepped’ for pixmaps.
$ grep -Rl "pixmaps" .
Which yielded
./Changelog.txt
./Readme.txt
./linux/hub.cc
./linux/mainwindow.cc
./SConstruct
And then and there I found what I was seeking.
// Load icons. We need to do this in the code and not in the .glade file,
// otherwise we won't always find the images.
string file, path = WulforManager::get()->getPath() + "/pixmaps/";
WulforManager::get()->getPath() was the method I needed. Now the new code in privatemessage.cc read
if (BOOLSETTING(PRIVATE_MESSAGE_BEEP_OPEN)){
//Added by AppleGrew
const char *sndCmd = getenv("LINUX_DCPP_SND");
if(!sndCmd) {
string cmd = "aplay \"" + WulforManager::get()->getPath() + "/ping.wav\"";
system(cmd.data());
}else{
system(sndCmd);
}[/code]
This was it. Nice and smooth. I still don't know anything about WulforManager or SettingsManager declarations or the GTK libraries, yet I could finish this up fast and smoothly. All thanks to grep!
The title says it all. If you don’t know what a Magic Packet is then read here. Below is the code of a shell script (I call magic_shutdown) that uses tcpdump to listen for Magic Packets. When it receives on then the shell script verifies its content to make sure that this packet was meant for this computer. Note this script doesn’t require that your network interface card support Wake-on-LAN. It has no special hardware dependencies.
All-in-all, this script lets you create create a shortcut which will act as remote power button for your computer. Press it to turn the computer ON. Press it again to turn the computer OFF.
Get magic_shutdown‘s code
License: GNU Public License version 3.
[code lang=”bash”]#!/bin/bash
#Author:AppleGrew
#License:GPL version 3
listenPort=9
interface="eth0"
#Forking to daemonize…
if [[ "$2" != "forked" ]]
then
echo "Forking $0…"
"$0" "$1" forked &
echo "Forked."
exit 0
fi
#Creating pid file
ppid=$$
echo $ppid >"$1"
echo "Started"
mac=`ifconfig "$interface"|head -n1|sed -e ‘s/.*HWaddr \([0-9:a-fA-F]*\)/\1/g’ -e ‘s/://g’`
pckt_expect=`echo "ff ff ff ff ff ff $mac $mac $mac $mac $mac $mac $mac $mac"|sed ‘s/ //g’|tr ‘A-Z’ ‘a-z’`
while `true`
do
pckt_data=`tcpdump -i "$interface" -x -c 1 udp port ${listenPort}`
if [[ $? != 0 ]]
then
echo "tcpdump returned error."
exit 1
fi
pckt_data=`echo "$pckt_data" | \
grep ‘0x[0-9]*:’| \
tr ‘A-Z’ ‘a-z’| \
sed ‘s/[ \t]//g’| \
sed ‘s/0x[0-9]*:\([0-9a-f]*\)/\1/g’| \
tr -d ‘\n\r’| \
cut -c 57-`
if [[ "$pckt_data" == "$pckt_expect" ]]
then
echo "Matched! Received Magic packet shutting down…"
shutdown -P now #Not recommended
#For Gnome #Doesn’t work dunno why?
#dbus-send –session –dest=org.gnome.PowerManager \
# –type=method_call –print-reply –reply-timeout=2000 \
# /org/gnome/PowerManager org.gnome.PowerManager.Shutdown
#For KDE 3.5
#dcop `dcop|grep power-manager` power-manager shutdown
exit 0
fi
done
echo "EXITED"
exit 0[/code]
Below is the startup script that must be used to launch magic_shutdown script.
Get launch_magic_shutdown‘s code
License: GNU Public License version 3.
[code lang=”bash”]#!/bin/bash
#Author:AppleGrew
#License:GPL version 3
SCRIPT="/opt/magic_shutdown"
PID_FILE="/var/run/magic_shutdown.pid"
case "$1" in
start)
test -f "$PID_FILE" && echo "Already Running…" && exit 1
"$SCRIPT" "$PID_FILE"
echo "Started"
;;
stop)
pid=`cat "$PID_FILE"`
tcpPid=`pgrep -P $pid tcpdump`
kill -9 $pid
kill -2 $tcpPid
if [ -f "$PID_FILE" ] && ! ps -p $pid >/dev/null
then
rm -f "$PID_FILE"
else
echo "Failed to delete pid file. Maybe its already deleted."
fi
echo "Stopped"
;;
esac[/code]
Installations:-
Assuming that you have downloaded the above two codes into your home directory. Now run the following commands.
sudo cp launch_magic_shutdown /etc/init.d
sudo chmod a+x /etc/init.d/launch_magic_shutdown
cd /etc/rc2.d
sudo ln -s ../init.d/launch_magic_shutdown S99launch_magic_shutdown
sudo cp magic_shutdown /opt/magic_shutdown
sudo chmod a+x /opt/magic_shutdown
Hope this helps. Report in the comments section if you encounter any problem.
Update: Stuart’s Script
Stuart (see comment section) posted his version of magic_shutdown script. If the above one doesn’t work then maybe you should give this one a try.
[code lang=”bash”]#!/bin/sh
#Author: Stuart
#Original Author:AppleGrew
#License:GPL version 3
#Forking to daemonize…
if [[ "$2" != "forked" ]]
then
echo "Forking $0…"
"$0" "$1" forked &
echo "Forked."
exit 0
fi
#Creating pid file
ppid=$$
echo $ppid >"$1"
echo "Started"
interface=`route -n | grep "^0.0.0.0" | awk -F " " ‘{print $8}’`
mac=`ifconfig "$interface"|head -n1|sed -e ‘s/.*HWaddr \([0-9:a-fA-F]*\)/\1/g’ -e ‘s/://g’`
pckt_expect=`echo "$mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac"|sed ‘s/ //g’|tr ‘A-Z’ ‘a-z’`
while `true`
do
pckt_data=`tcpdump -i "$interface" -s 0 -x -c 1 \( \(ether dst "$mac" and not ip and not arp and not rarp\) or \(udp port 9\) \)`
if [[ $? != 0 ]]
then
echo "tcpdump returned error."
exit 1
fi
pckt_data=`echo "$pckt_data" | \
grep ‘0x[0-9]*:’| \
tr ‘A-Z’ ‘a-z’| \
sed ‘s/[ \t]//g’| \
sed ‘s/0x[0-9]*:\([0-9a-f]*\)/\1/g’| \
tr -d ‘\n\r’ | \
awk -F "ffffffffffff" ‘{print $2}’`
if [[ "$pckt_data" == "$pckt_expect" ]]
then
echo "Matched! Received Magic packet shutting down…"
rm -f $1
/sbin/poweroff
exit 0
fi
done
echo "EXITED"
exit 0[/code]
About the script
This is a KDE (may not work in KDE 4) only shell script which changes wallpaper every few minutes as set by you. KDE too has a built-in feature to change wallpaper but it has few limitations:-
This script allows you to apply different picture position settings to pictures from different directories. e.g. if you use the following settings
picDir=”/home/geek/Pictures”
shapeDir=”Rectangle Square Tall”
shapeMode=”8 8 5″
Then pictures from /home/geek/Pictures/Rectangle and /home/geek/Pictures/Square will be shown using Scale & Crop position setting, and pictures from /home/geek/Pictures/Tall will be Titled Maxpect. Following is the table for which number stands for what position setting.
This script is best used with my iflickrDown script (see here).
The code
License: GNU Public License version 3.
[code lang=”bash”]#!/bin/bash
#Coded by AppleGrew
#License: GPL version 3
#############################################
############Alternative way to set###########
##########the following variables############
#Create another shell script and export it #
#from there. #
#===============SAMPLE=======================
# #!/bin/bash
# export picDir="/home/geek/Pictures" #Donot put ‘/’ at the end
# export shapeDir="Square Rectangle Tall"
# export shapeMode="8 8 5"
# export changeWallIntv=2 #in mins
#
# ./autoWallChange >/tmp/autoWall.log & #Launching the main program.
############Configs##########################
picDir="" #Donot put ‘/’ at the end
shapeDir=""
shapeMode=""
changeWallIntv=1 #in mins
#############################################
tmpFile="/tmp/autoWallChange.tmp"
lstFile="/tmp/autoWallChange.lst"
fileLen=0
factor=0
shapeDir=( $shapeDir )
shapeMode=( $shapeMode )
echo "${shapeDir[@]}"
echo "${shapeMode[@]}"
function refreshFileList(){
local DIR_PATH=$1
local sM=$2
echo "Refreshing content of ‘$DIR_PATH’, shape mode is $sM"
if [ -a "$DIR_PATH" ] && [ -d "$DIR_PATH" ] && [ -w "$DIR_PATH" ]
then
for f in `find "$DIR_PATH" -type f -print | sed ‘s/ /|/g’`
do
matchFound=0
for fl in `cat "$tmpFile"`
do
fl=`echo "$fl"|sed -e ‘s/\([^>]*\)>\([^>]*\)/\1\n\2/g’|head -n 1|tail -n 1`
[[ "$fl" == "$f" ]] && matchFound=1 && break
done
[[ $matchFound == 0 ]] && printf "%s>%d\n" $f $sM >>"$tmpFile" && let ‘fileLen++’
done
let ‘factor=(fileLen-1)*100000000/32767’
fi
echo "Refreshed"
}
printf "">"$tmpFile" #Creating new empty file.
i=0
for shape in ${shapeDir[@]}
do
test -a "$picDir/$shape" && find -L "$picDir/$shape" -type f -print > "$lstFile.$i"
test -a "$picDir/$shape" && refreshFileList "$picDir/$shape" ${shapeMode[$i]}
let ‘i++’
done
shownPicsLine=0
lastL=""
totShown=0
RANDOM=$$
while true
do
let ‘l=(factor*RANDOM+100000000)/100000000’
test $totShown -ge $fileLen && lastL="" && totShown=0
while echo "$lastL" | grep -o "\"$l\"" > /dev/null
do
let "l++"
test $l -gt $fileLen && l=1
done
lastL="${lastL}\"$l\""
let "totShown++"
pfileL=`cat "$tmpFile"|head -n $l|tail -n 1`
pfilePath=`echo "$pfileL"|sed -e ‘s/\([^>]*\)>\([^>]*\)/\1\n\2/g’|head -n 1|tail -n 1|sed ‘s/|/ /g’`
pfileMode=`echo "$pfileL"|sed -e ‘s/\([^>]*\)>\([^>]*\)/\1\n\2/g’|head -n 2|tail -n 1`
if [ $totShown -ge $fileLen ]
then
lastL=""
totShown=0
fi
[ -f "$pfilePath" ] && dcop kdesktop KBackgroundIface setWallpaper "$pfilePath" "$pfileMode"
i=0
for shape in ${shapeDir[@]}
do
if test -a "$picDir/$shape" && ! find -L "$picDir/$shape" -type f -print | diff "$lstFile.$i" ->/dev/null
then
echo "’$picDir/$shape’ content changed"
refreshFileList "$picDir/$shape" ${shapeMode[$i]}
find -L "$picDir/$shape" -type f -print > "$lstFile.$i"
fi
let ‘i++’
done
echo "sleeping"
sleep "${changeWallIntv}m"
done<[/code]