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; +}