diff --git a/PersianCalendar@oxygenws.com/PrayTimes.js b/PersianCalendar@oxygenws.com/PrayTimes.js
new file mode 100644
index 0000000..5559ccc
--- /dev/null
+++ b/PersianCalendar@oxygenws.com/PrayTimes.js
@@ -0,0 +1,588 @@
+//--------------------- Copyright Block ----------------------
+/*
+
+PrayTimes.js: Prayer Times Calculator (ver 2.3)
+Copyright (C) 2007-2011 PrayTimes.org
+
+Developer: Hamid Zarrabi-Zadeh
+License: GNU LGPL v3.0
+
+TERMS OF USE:
+ Permission is granted to use this code, with or
+ without modification, in any website or application
+ provided that credit is given to the original work
+ with a link back to PrayTimes.org.
+
+This program is distributed in the hope that it will
+be useful, but WITHOUT ANY WARRANTY.
+
+PLEASE DO NOT REMOVE THIS COPYRIGHT BLOCK.
+
+*/
+
+
+//--------------------- Help and Manual ----------------------
+/*
+
+User's Manual:
+http://praytimes.org/manual
+
+Calculation Formulas:
+http://praytimes.org/calculation
+
+
+
+//------------------------ User Interface -------------------------
+
+
+ getTimes (date, coordinates [, timeZone [, dst [, timeFormat]]])
+
+ setMethod (method) // set calculation method
+ adjust (parameters) // adjust calculation parameters
+ tune (offsets) // tune times by given offsets
+
+ getMethod () // get calculation method
+ getSetting () // get current calculation parameters
+ getOffsets () // get current time offsets
+
+
+//------------------------- Sample Usage --------------------------
+
+
+ var PT = new PrayTimes('ISNA');
+ var times = PT.getTimes(new Date(), [43, -80], -5);
+ document.write('Sunrise = '+ times.sunrise)
+
+
+*/
+
+
+//----------------------- PrayTimes Class ------------------------
+
+
+function PrayTimes(method) {
+
+
+ //------------------------ Constants --------------------------
+ var
+
+ // Time Names
+ timeNames = {
+ imsak : 'Imsak',
+ fajr : 'Fajr',
+ sunrise : 'Sunrise',
+ dhuhr : 'Dhuhr',
+ asr : 'Asr',
+ sunset : 'Sunset',
+ maghrib : 'Maghrib',
+ isha : 'Isha',
+ midnight : 'Midnight'
+ },
+
+ // Calculation Methods
+ methods = {
+ MWL: {
+ name: 'Muslim World League',
+ params: { fajr: 18, isha: 17 } },
+ ISNA: {
+ name: 'Islamic Society of North America (ISNA)',
+ params: { fajr: 15, isha: 15 } },
+ Egypt: {
+ name: 'Egyptian General Authority of Survey',
+ params: { fajr: 19.5, isha: 17.5 } },
+ Makkah: {
+ name: 'Umm Al-Qura University, Makkah',
+ params: { fajr: 18.5, isha: '90 min' } }, // fajr was 19 degrees before 1430 hijri
+ Karachi: {
+ name: 'University of Islamic Sciences, Karachi',
+ params: { fajr: 18, isha: 18 } },
+ Tehran: {
+ name: 'Institute of Geophysics, University of Tehran',
+ params: { fajr: 17.7, isha: 14, maghrib: 4.5, midnight: 'Jafari' } }, // isha is not explicitly specified in this method
+ Jafari: {
+ name: 'Shia Ithna-Ashari, Leva Institute, Qum',
+ params: { fajr: 16, isha: 14, maghrib: 4, midnight: 'Jafari' } }
+ },
+
+
+ // Default Parameters in Calculation Methods
+ defaultParams = {
+ maghrib: '0 min', midnight: 'Standard'
+
+ },
+
+
+ //----------------------- Parameter Values ----------------------
+ /*
+
+ // Asr Juristic Methods
+ asrJuristics = [
+ 'Standard', // Shafi`i, Maliki, Ja`fari, Hanbali
+ 'Hanafi' // Hanafi
+ ],
+
+
+ // Midnight Mode
+ midnightMethods = [
+ 'Standard', // Mid Sunset to Sunrise
+ 'Jafari' // Mid Sunset to Fajr
+ ],
+
+
+ // Adjust Methods for Higher Latitudes
+ highLatMethods = [
+ 'NightMiddle', // middle of night
+ 'AngleBased', // angle/60th of night
+ 'OneSeventh', // 1/7th of night
+ 'None' // No adjustment
+ ],
+
+
+ // Time Formats
+ timeFormats = [
+ '24h', // 24-hour format
+ '12h', // 12-hour format
+ '12hNS', // 12-hour format with no suffix
+ 'Float' // floating point number
+ ],
+ */
+
+
+ //---------------------- Default Settings --------------------
+
+ calcMethod = 'Makkah',
+
+ // do not change anything here; use adjust method instead
+ setting = {
+ imsak : '10 min',
+ dhuhr : '0 min',
+ asr : 'Standard',
+ highLats : 'NightMiddle'
+ },
+
+ timeFormat = '24h',
+ timeSuffixes = ['am', 'pm'],
+ invalidTime = '-----',
+
+ numIterations = 1,
+ offset = {},
+
+
+ //----------------------- Local Variables ---------------------
+
+ lat, lng, elv, // coordinates
+ timeZone, jDate; // time variables
+
+
+ //---------------------- Initialization -----------------------
+
+
+ // set methods defaults
+ var defParams = defaultParams;
+ for (var i in methods) {
+ var params = methods[i].params;
+ for (var j in defParams)
+ if ((typeof(params[j]) == 'undefined'))
+ params[j] = defParams[j];
+ };
+
+ // initialize settings
+ calcMethod = methods[method] ? method : calcMethod;
+ var params = methods[calcMethod].params;
+ for (var id in params)
+ setting[id] = params[id];
+
+ // init time offsets
+ for (var i in timeNames)
+ offset[i] = 0;
+
+
+
+ //----------------------- Public Functions ------------------------
+ return {
+
+ persianMap : {
+ imsak : 'امساک',
+ fajr : 'اذان صبح',
+ sunrise : 'طلوع آفتاب',
+ dhuhr : 'اذان ظهر',
+ asr : 'اذان عصر',
+ sunset : 'غروب آفتاب',
+ maghrib : 'نماز مغرب',
+ isha : 'نماز عشاء',
+ midnight : 'نیمه شب'
+ },
+ // set calculation method
+ setMethod: function(method) {
+ if (methods[method]) {
+ this.adjust(methods[method].params);
+ calcMethod = method;
+ }
+ },
+
+
+ // set calculating parameters
+ adjust: function(params) {
+ for (var id in params)
+ setting[id] = params[id];
+ },
+
+
+ // set time offsets
+ tune: function(timeOffsets) {
+ for (var i in timeOffsets)
+ offset[i] = timeOffsets[i];
+ },
+
+
+ // get current calculation method
+ getMethod: function() { return calcMethod; },
+
+ // get current setting
+ getSetting: function() { return setting; },
+
+ // get current time offsets
+ getOffsets: function() { return offset; },
+
+ // get default calc parametrs
+ getDefaults: function() { return methods; },
+
+
+ // return prayer times for a given date
+ getTimes: function(date, coords, timezone, dst, format) {
+ lat = 1* coords[0];
+ lng = 1* coords[1];
+ elv = coords[2] ? 1* coords[2] : 0;
+ timeFormat = format || timeFormat;
+ if (date.constructor === Date)
+ date = [date.getFullYear(), date.getMonth()+ 1, date.getDate()];
+ if (typeof(timezone) == 'undefined' || timezone == 'auto')
+ timezone = this.getTimeZone(date);
+ if (typeof(dst) == 'undefined' || dst == 'auto')
+ dst = this.getDst(date);
+ timeZone = 1* timezone+ (1* dst ? 1 : 0);
+ jDate = this.julian(date[0], date[1], date[2])- lng/ (15* 24);
+
+ return this.computeTimes();
+ },
+
+
+ // convert float time to the given format (see timeFormats)
+ getFormattedTime: function(time, format, suffixes) {
+ if (isNaN(time))
+ return invalidTime;
+ if (format == 'Float') return time;
+ suffixes = suffixes || timeSuffixes;
+
+ time = DMath.fixHour(time+ 0.5/ 60); // add 0.5 minutes to round
+ var hours = Math.floor(time);
+ var minutes = Math.floor((time- hours)* 60);
+ var suffix = (format == '12h') ? suffixes[hours < 12 ? 0 : 1] : '';
+ var hour = (format == '24h') ? this.twoDigitsFormat(hours) : ((hours+ 12 -1)% 12+ 1);
+ return hour+ ':'+ this.twoDigitsFormat(minutes)+ (suffix ? ' '+ suffix : '');
+ },
+
+
+ //---------------------- Calculation Functions -----------------------
+
+
+ // compute mid-day time
+ midDay: function(time) {
+ var eqt = this.sunPosition(jDate+ time).equation;
+ var noon = DMath.fixHour(12- eqt);
+ return noon;
+ },
+
+
+ // compute the time at which sun reaches a specific angle below horizon
+ sunAngleTime: function(angle, time, direction) {
+ var decl = this.sunPosition(jDate+ time).declination;
+ var noon = this.midDay(time);
+ var t = 1/15* DMath.arccos((-DMath.sin(angle)- DMath.sin(decl)* DMath.sin(lat))/
+ (DMath.cos(decl)* DMath.cos(lat)));
+ return noon+ (direction == 'ccw' ? -t : t);
+ },
+
+
+ // compute asr time
+ asrTime: function(factor, time) {
+ var decl = this.sunPosition(jDate+ time).declination;
+ var angle = -DMath.arccot(factor+ DMath.tan(Math.abs(lat- decl)));
+ return this.sunAngleTime(angle, time);
+ },
+
+
+ // compute declination angle of sun and equation of time
+ // Ref: http://aa.usno.navy.mil/faq/docs/SunApprox.php
+ sunPosition: function(jd) {
+ var D = jd - 2451545.0;
+ var g = DMath.fixAngle(357.529 + 0.98560028* D);
+ var q = DMath.fixAngle(280.459 + 0.98564736* D);
+ var L = DMath.fixAngle(q + 1.915* DMath.sin(g) + 0.020* DMath.sin(2*g));
+
+ var R = 1.00014 - 0.01671* DMath.cos(g) - 0.00014* DMath.cos(2*g);
+ var e = 23.439 - 0.00000036* D;
+
+ var RA = DMath.arctan2(DMath.cos(e)* DMath.sin(L), DMath.cos(L))/ 15;
+ var eqt = q/15 - DMath.fixHour(RA);
+ var decl = DMath.arcsin(DMath.sin(e)* DMath.sin(L));
+
+ return {declination: decl, equation: eqt};
+ },
+
+
+ // convert Gregorian date to Julian day
+ // Ref: Astronomical Algorithms by Jean Meeus
+ julian: function(year, month, day) {
+ if (month <= 2) {
+ year -= 1;
+ month += 12;
+ };
+ var A = Math.floor(year/ 100);
+ var B = 2- A+ Math.floor(A/ 4);
+
+ var JD = Math.floor(365.25* (year+ 4716))+ Math.floor(30.6001* (month+ 1))+ day+ B- 1524.5;
+ return JD;
+ },
+
+
+ //---------------------- Compute Prayer Times -----------------------
+
+
+ // compute prayer times at given julian date
+ computePrayerTimes: function(times) {
+ times = this.dayPortion(times);
+ var params = setting;
+
+ var imsak = this.sunAngleTime(this.eval(params.imsak), times.imsak, 'ccw');
+ var fajr = this.sunAngleTime(this.eval(params.fajr), times.fajr, 'ccw');
+ var sunrise = this.sunAngleTime(this.riseSetAngle(), times.sunrise, 'ccw');
+ var dhuhr = this.midDay(times.dhuhr);
+ var asr = this.asrTime(this.asrFactor(params.asr), times.asr);
+ var sunset = this.sunAngleTime(this.riseSetAngle(), times.sunset);;
+ var maghrib = this.sunAngleTime(this.eval(params.maghrib), times.maghrib);
+ var isha = this.sunAngleTime(this.eval(params.isha), times.isha);
+
+ return {
+ imsak: imsak, fajr: fajr, sunrise: sunrise, dhuhr: dhuhr,
+ asr: asr, sunset: sunset, maghrib: maghrib, isha: isha
+ };
+ },
+
+
+ // compute prayer times
+ computeTimes: function() {
+ // default times
+ var times = {
+ imsak: 5, fajr: 5, sunrise: 6, dhuhr: 12,
+ asr: 13, sunset: 18, maghrib: 18, isha: 18
+ };
+
+ // main iterations
+ for (var i=1 ; i<=numIterations ; i++)
+ times = this.computePrayerTimes(times);
+
+ times = this.adjustTimes(times);
+
+ // add midnight time
+ times.midnight = (setting.midnight == 'Jafari') ?
+ times.sunset+ this.timeDiff(times.sunset, times.fajr)/ 2 :
+ times.sunset+ this.timeDiff(times.sunset, times.sunrise)/ 2;
+
+ times = this.tuneTimes(times);
+ return this.modifyFormats(times);
+ },
+
+
+ // adjust times
+ adjustTimes: function(times) {
+ var params = setting;
+ for (var i in times)
+ times[i] += timeZone- lng/ 15;
+
+ if (params.highLats != 'None')
+ times = this.adjustHighLats(times);
+
+ if (this.isMin(params.imsak))
+ times.imsak = times.fajr- this.eval(params.imsak)/ 60;
+ if (this.isMin(params.maghrib))
+ times.maghrib = times.sunset+ this.eval(params.maghrib)/ 60;
+ if (this.isMin(params.isha))
+ times.isha = times.maghrib+ this.eval(params.isha)/ 60;
+ times.dhuhr += this.eval(params.dhuhr)/ 60;
+
+ return times;
+ },
+
+
+ // get asr shadow factor
+ asrFactor: function(asrParam) {
+ var factor = {Standard: 1, Hanafi: 2}[asrParam];
+ return factor || this.eval(asrParam);
+ },
+
+
+ // return sun angle for sunset/sunrise
+ riseSetAngle: function() {
+ //var earthRad = 6371009; // in meters
+ //var angle = DMath.arccos(earthRad/(earthRad+ elv));
+ var angle = 0.0347* Math.sqrt(elv); // an approximation
+ return 0.833+ angle;
+ },
+
+
+ // apply offsets to the times
+ tuneTimes: function(times) {
+ for (var i in times)
+ times[i] += offset[i]/ 60;
+ return times;
+ },
+
+
+ // convert times to given time format
+ modifyFormats: function(times) {
+ for (var i in times)
+ times[i] = this.getFormattedTime(times[i], timeFormat);
+ return times;
+ },
+
+
+ // adjust times for locations in higher latitudes
+ adjustHighLats: function(times) {
+ var params = setting;
+ var nightTime = this.timeDiff(times.sunset, times.sunrise);
+
+ times.imsak = this.adjustHLTime(times.imsak, times.sunrise, this.eval(params.imsak), nightTime, 'ccw');
+ times.fajr = this.adjustHLTime(times.fajr, times.sunrise, this.eval(params.fajr), nightTime, 'ccw');
+ times.isha = this.adjustHLTime(times.isha, times.sunset, this.eval(params.isha), nightTime);
+ times.maghrib = this.adjustHLTime(times.maghrib, times.sunset, this.eval(params.maghrib), nightTime);
+
+ return times;
+ },
+
+
+ // adjust a time for higher latitudes
+ adjustHLTime: function(time, base, angle, night, direction) {
+ var portion = this.nightPortion(angle, night);
+ var timeDiff = (direction == 'ccw') ?
+ this.timeDiff(time, base):
+ this.timeDiff(base, time);
+ if (isNaN(time) || timeDiff > portion)
+ time = base+ (direction == 'ccw' ? -portion : portion);
+ return time;
+ },
+
+
+ // the night portion used for adjusting times in higher latitudes
+ nightPortion: function(angle, night) {
+ var method = setting.highLats;
+ var portion = 1/2 // MidNight
+ if (method == 'AngleBased')
+ portion = 1/60* angle;
+ if (method == 'OneSeventh')
+ portion = 1/7;
+ return portion* night;
+ },
+
+
+ // convert hours to day portions
+ dayPortion: function(times) {
+ for (var i in times)
+ times[i] /= 24;
+ return times;
+ },
+
+
+ //---------------------- Time Zone Functions -----------------------
+
+
+ // get local time zone
+ getTimeZone: function(date) {
+ var year = date[0];
+ var t1 = this.gmtOffset([year, 0, 1]);
+ var t2 = this.gmtOffset([year, 6, 1]);
+ return Math.min(t1, t2);
+ },
+
+
+ // get daylight saving for a given date
+ getDst: function(date) {
+ return 1* (this.gmtOffset(date) != this.getTimeZone(date));
+ },
+
+
+ // GMT offset for a given date
+ gmtOffset: function(date) {
+ var localDate = new Date(date[0], date[1]- 1, date[2], 12, 0, 0, 0);
+ var GMTString = localDate.toGMTString();
+ var GMTDate = new Date(GMTString.substring(0, GMTString.lastIndexOf(' ')- 1));
+ var hoursDiff = (localDate- GMTDate) / (1000* 60* 60);
+ return hoursDiff;
+ },
+
+
+ //---------------------- Misc Functions -----------------------
+
+ // convert given string into a number
+ eval: function(str) {
+ return 1* (str+ '').split(/[^0-9.+-]/)[0];
+ },
+
+
+ // detect if input contains 'min'
+ isMin: function(arg) {
+ return (arg+ '').indexOf('min') != -1;
+ },
+
+
+ // compute the difference between two times
+ timeDiff: function(time1, time2) {
+ return DMath.fixHour(time2- time1);
+ },
+
+
+ // add a leading 0 if necessary
+ twoDigitsFormat: function(num) {
+ return (num <10) ? '0'+ num : num;
+ }
+
+ }
+}
+
+
+
+//---------------------- Degree-Based Math Class -----------------------
+
+
+var DMath = {
+
+ dtr: function(d) { return (d * Math.PI) / 180.0; },
+ rtd: function(r) { return (r * 180.0) / Math.PI; },
+
+ sin: function(d) { return Math.sin(this.dtr(d)); },
+ cos: function(d) { return Math.cos(this.dtr(d)); },
+ tan: function(d) { return Math.tan(this.dtr(d)); },
+
+ arcsin: function(d) { return this.rtd(Math.asin(d)); },
+ arccos: function(d) { return this.rtd(Math.acos(d)); },
+ arctan: function(d) { return this.rtd(Math.atan(d)); },
+
+ arccot: function(x) { return this.rtd(Math.atan(1/x)); },
+ arctan2: function(y, x) { return this.rtd(Math.atan2(y, x)); },
+
+ fixAngle: function(a) { return this.fix(a, 360); },
+ fixHour: function(a) { return this.fix(a, 24 ); },
+
+ fix: function(a, b) {
+ a = a- b* (Math.floor(a/ b));
+ return (a < 0) ? a+ b : a;
+ }
+}
+
+
+//---------------------- Init Object -----------------------
+
+
+var prayTimes = new PrayTimes();
+
+
diff --git a/PersianCalendar@oxygenws.com/calendar.js b/PersianCalendar@oxygenws.com/calendar.js
index f5728ff..cbfe986 100644
--- a/PersianCalendar@oxygenws.com/calendar.js
+++ b/PersianCalendar@oxygenws.com/calendar.js
@@ -9,6 +9,8 @@ const convenience = extension.imports.convenience;
const PersianDate = extension.imports.PersianDate;
const HijriDate = extension.imports.HijriDate;
+const PrayTimes = extension.imports.PrayTimes.prayTimes;
+const player = extension.imports.sound.player;
const str = extension.imports.strFunctions;
const Events = extension.imports.Events;
@@ -45,7 +47,7 @@ Calendar.prototype = {
});
this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
-
+ PrayTimes.setMethod('Tehran');
this._buildHeader();
},
@@ -421,6 +423,57 @@ Calendar.prototype = {
}));
}
+ if(Schema.get_boolean('praytime-visible'))
+ {
+ let _prayBox_v = new St.BoxLayout({style_class: 'button pcalendar-praytimes-container', vertical: true, x_expand: true});
+
+ let _prayTimes = PrayTimes.getTimes(g_selectedDate, [Schema.get_double('praytime-lat') , Schema.get_double('praytime-lng')], Schema.get_double('praytime-timezone'));
+
+ let i=0;
+ let _prayColumnBox = new St.BoxLayout({style_class: 'pcalendar-praytimes-box', x_expand: true});
+ for(let key in _prayTimes)
+ {
+
+ _prayColumnBox.add(new St.Label({
+ text: str.format(_prayTimes[key]),
+ style_class: 'pcalendar-praytimes-item pcalendar-praytimes-time',
+ x_expand: true,
+ }));
+
+
+ _prayColumnBox.add(new St.Label({
+ text: PrayTimes.persianMap[key],
+ style_class: 'pcalendar-praytimes-item pcalendar-praytimes-key',
+ x_expand: true,
+ }));
+
+ if( ++i % 2 === 0)
+ {
+ _prayBox_v.add(_prayColumnBox);
+ _prayColumnBox = new St.BoxLayout({style_class: 'pcalendar-praytimes-box', x_expand: true});
+ }
+
+ }
+
+ this.actor.layout_manager.attach(_prayBox_v, 0, ++row, 7, i-1);
+ row+=i;
+ if(player.isPlaying())
+ {
+ let btn = new St.Button({label: 'توقف پخش اذان', style_class : 'button pcalendar-praytimes-azan'});
+ btn.connect('clicked',Lang.bind(btn, function(){
+ player.pause();
+ }));
+ this.actor.layout_manager.attach(btn, 0, ++row, 7, 1);
+ }
+
+
+ // let _label = new St.Label();
+ // _label.set_text(_textBuilder.join('\n'));
+ // _prayBox_h.add(_label, {expand: true, x_fill: true, x_align: St.Align.MIDDLE});
+ // {"imsak":"04:43","fajr":"04:53","sunrise":"06:16","dhuhr":"12:14","asr":"15:37","sunset":"18:11","maghrib":"18:29","isha":"19:16","midnight":"23:32"}
+ }
+
+
// add event box for selected date
events = ev.getEvents(g_selectedDate);
@@ -437,5 +490,14 @@ Calendar.prototype = {
bottomLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
_eventBox.add(bottomLabel, {expand: true, x_fill: true, y_fill: true, x_align: St.Align.MIDDLE});
}
+ },
+
+ checkPrayTime: function(){
+ let now = new Date();
+ if(now.getSeconds() >= 3 || !Schema.get_boolean('praytime-play')) return;
+ let _prayTimes = PrayTimes.getTimes(now, [Schema.get_double('praytime-lat') , Schema.get_double('praytime-lng')], Schema.get_double('praytime-timezone'));
+ now = now.getHours() + ':' + now.getMinutes();
+ if([_prayTimes.fajr,_prayTimes.dhuhr,_prayTimes.maghrib].includes(now))
+ player.setVolume(1);
}
};
diff --git a/PersianCalendar@oxygenws.com/extension.js b/PersianCalendar@oxygenws.com/extension.js
index 3b0651c..de1ca05 100644
--- a/PersianCalendar@oxygenws.com/extension.js
+++ b/PersianCalendar@oxygenws.com/extension.js
@@ -226,6 +226,8 @@ const PersianCalendar = new Lang.Class({
that._calendar.setDate(now);
}
}));
+
+ this._prayerTimeLoop();
},
_updateDate: function (skip_notification, force) {
@@ -277,6 +279,15 @@ const PersianCalendar = new Lang.Class({
return true;
},
+ _prayerTimeLoop: function(){
+ if (this._prayerTimeout) {
+ MainLoop.source_remove(this._prayerTimeout);
+ this._prayerTimeout = null;
+ }
+ this._prayerTimeout = MainLoop.timeout_add(60000 - (new Date().getSeconds() * 1000), Lang.bind(this,this._prayerTimeLoop));
+ this._calendar.checkPrayTime();
+ },
+
_generateConverterPart: function () {
// Add date conversion button
let converterMenu = new PopupMenu.PopupSubMenuMenuItem('تبدیل تاریخ');
@@ -533,6 +544,7 @@ function enable() {
_indicator._updateDate(!Schema.get_boolean('startup-notification'));
_timer = MainLoop.timeout_add(3000, Lang.bind(_indicator, _indicator._updateDate));
+
// install fonts
let path = extension.dir.get_path();
GLib.spawn_sync(
diff --git a/PersianCalendar@oxygenws.com/prefs.js b/PersianCalendar@oxygenws.com/prefs.js
index 617cda5..d1c9b52 100644
--- a/PersianCalendar@oxygenws.com/prefs.js
+++ b/PersianCalendar@oxygenws.com/prefs.js
@@ -125,6 +125,33 @@ const App = new Lang.Class({
this.vbox2.add(item);
Schema.bind('event-world', item, 'active', Gio.SettingsBindFlags.DEFAULT);
+ //PrayTimes
+ this.vbox2.add(new Gtk.Label({
+ label: _('PrayTime:\n("PrayTime" based on geographical location)'),
+ use_markup: true
+ }));
+ item = new Gtk.CheckButton({label: _('Show Pray Time')});
+ this.vbox2.add(item);
+ Schema.bind('praytime-visible', item, 'active', Gio.SettingsBindFlags.DEFAULT);
+
+ item = new Gtk.CheckButton({label: _('Play Azaan')});
+ this.vbox2.add(item);
+ Schema.bind('praytime-play', item, 'active', Gio.SettingsBindFlags.DEFAULT);
+
+
+ let _item = this.createTextEntry('praytime-lat', 'Latitude: ');
+ this.vbox2.add(_item.hbox);
+ if(_item.comment) this.vbox2.add(_item.comment);
+
+ _item = this.createTextEntry('praytime-lng', 'Longitude: ');
+ this.vbox2.add(_item.hbox);
+ if(_item.comment) this.vbox2.add(_item.comment);
+
+ _item = this.createTextEntry('praytime-timezone', 'Timezone: ');
+ this.vbox2.add(_item.hbox);
+ if(_item.comment) this.vbox2.add(_item.comment);
+
+
// COLOR
this.vbox3.add(new Gtk.Label({label: _('Widget Properties:')}));
@@ -194,6 +221,25 @@ const App = new Lang.Class({
this.main_hbox.show_all();
},
+ createTextEntry: function(value, labelText, commentText){
+ let label = new Gtk.Label({label: labelText});
+ let format = new Gtk.Entry();
+ let hbox = new Gtk.HBox();
+ hbox.add(label);
+ hbox.add(format);
+ let comment = null;
+ if(commentText)
+ comment = new Gtk.Label({
+ label: _(commentText),
+ use_markup: true
+ });
+ format.set_text(Schema.get_double(value).toString());
+ format.connect('changed', function (innerFormat) {
+ Schema.set_string(value, innerFormat.text);
+ });
+
+ return {hbox:hbox,comment:comment};
+ },
_scaleRound: function (value) {
// Based on gtk/gtkcoloreditor.c
diff --git a/PersianCalendar@oxygenws.com/schemas/gschemas.compiled b/PersianCalendar@oxygenws.com/schemas/gschemas.compiled
index fd41dcc..2af0c1a 100644
Binary files a/PersianCalendar@oxygenws.com/schemas/gschemas.compiled and b/PersianCalendar@oxygenws.com/schemas/gschemas.compiled differ
diff --git a/PersianCalendar@oxygenws.com/schemas/org.gnome.shell.extensions.persian-calendar.gschema.xml b/PersianCalendar@oxygenws.com/schemas/org.gnome.shell.extensions.persian-calendar.gschema.xml
index d114d81..3ff61f3 100644
--- a/PersianCalendar@oxygenws.com/schemas/org.gnome.shell.extensions.persian-calendar.gschema.xml
+++ b/PersianCalendar@oxygenws.com/schemas/org.gnome.shell.extensions.persian-calendar.gschema.xml
@@ -60,6 +60,31 @@
Display official international events
Display official international events.
+
+ true
+ Display PrayTime
+ Display Pray time based on location
+
+
+ true
+ Play Call to prayer song (Azaan)
+ Play Azan
+
+
+ 35.689202
+ Latitude
+ your location latitude
+
+
+ 51.388973
+ Latitude
+ your location latitude
+
+
+ 3.5
+ Timezone
+ Your timezone based on GMT
+
'%d'
Widget date format
diff --git a/PersianCalendar@oxygenws.com/sound.js b/PersianCalendar@oxygenws.com/sound.js
new file mode 100644
index 0000000..9e08677
--- /dev/null
+++ b/PersianCalendar@oxygenws.com/sound.js
@@ -0,0 +1,89 @@
+/* sound.js
+ *
+ * Copyright (C) 2017 Felipe Borges
+ *
+ * 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 3 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, see .
+ */
+
+
+const Gst = imports.gi.Gst;
+const GstAudio = imports.gi.GstAudio;
+
+const DEFAULT_VOLUME = 1;
+Gst.init(null);
+const SoundPlayer = class SoundPlayer {
+ constructor(sound) {
+ this.playbin = Gst.ElementFactory.make("playbin", sound.name);
+ this.playbin.set_property("uri", this.getUri(sound));
+ this.sink = Gst.ElementFactory.make("pulsesink", "sink");
+ this.playbin.set_property("audio-sink", this.sink);
+
+ this.prerolled = false;
+ let bus = this.playbin.get_bus();
+ bus.add_signal_watch();
+ bus.connect("message", (bus, msg) => {
+ if (msg != null) this._onMessageReceived(msg);
+ });
+ }
+
+ isPlaying() {
+ let [rv, state, pstate] = this.playbin.get_state(Gst.State.NULL);
+ return state === Gst.State.PLAYING;
+ }
+
+
+ play() {
+ this.playbin.set_state(Gst.State.PLAYING);
+
+ }
+
+ pause() {
+ this.playbin.set_state(Gst.State.NULL);
+ this.prerolled = false;
+ }
+
+ setVolume(value) {
+ this.playbin.set_volume(GstAudio.StreamVolumeFormat.LINEAR, value);
+ if (value == 0) {
+ this.playbin.set_state(Gst.State.NULL);
+ } else if (!this.isPlaying()) {
+ this.play();
+ }
+ }
+
+ _onMessageReceived(message) {
+ if (message.type == Gst.MessageType.SEGMENT_DONE) {
+ this.playbin.seek_simple(Gst.Format.TIME, Gst.SeekFlags.SEGMENT, 0);
+ }
+ if (message.type == Gst.MessageType.ASYNC_DONE) {
+ if (!this.prerolled) {
+ this.playbin.seek_simple(
+ Gst.Format.TIME,
+ Gst.SeekFlags.FLUSH | Gst.SeekFlags.SEGMENT,
+ 0
+ );
+ this.prerolled = true;
+ }
+ }
+
+ return true;
+ }
+
+ getUri(sound) {
+ /* All URIs are relative to $HOME. */
+ return Gst.filename_to_uri(sound.uri);
+ }
+};
+
+var player = new SoundPlayer({name:"test",uri:".local/share/gnome-shell/extensions/PersianCalendar@oxygenws.com/sounds/azan.mp3"});
\ No newline at end of file
diff --git a/PersianCalendar@oxygenws.com/sounds/azan.mp3 b/PersianCalendar@oxygenws.com/sounds/azan.mp3
new file mode 100644
index 0000000..c7934ac
Binary files /dev/null and b/PersianCalendar@oxygenws.com/sounds/azan.mp3 differ
diff --git a/PersianCalendar@oxygenws.com/stylesheet.css b/PersianCalendar@oxygenws.com/stylesheet.css
index 35d2a21..9c5d6cf 100644
--- a/PersianCalendar@oxygenws.com/stylesheet.css
+++ b/PersianCalendar@oxygenws.com/stylesheet.css
@@ -80,3 +80,28 @@
margin-left: 5px;
margin-right: 5px;
}
+
+.pcalendar-praytimes-container {
+ direction: rtl;
+ text-align: center;
+}
+.pcalendar-praytimes-box {
+ margin: 5px 0;
+
+}
+.pcalendar-praytimes-item{
+ margin: 0 5px;
+}
+.pcalendar-praytimes-key{
+ text-align: right;
+ width:70px;
+}
+.pcalendar-praytimes-time{
+ text-align: left;
+ width:40px;
+
+}
+
+.pcalendar-praytimes-azan{
+ background-color: #ff1648;
+}