commit 73a8336f3f141d65efd4c0a7d69ec7d418c79aaf Author: Hannes Janetzek Date: Fri Apr 30 21:16:09 2010 +0000 mpris gadget based on mpdule -- still very rough SVN revision: 48492 diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..040d2ff --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +iamsthitha +jeffdameth \ No newline at end of file diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..9690c3f --- /dev/null +++ b/COPYING @@ -0,0 +1,32 @@ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies of the Software and its Copyright notices. In addition publicly +documented acknowledgment must be given that this software has been used if no +source code of this software is made available publicly. Making the source +available publicly means including the source for this software with the +distribution, or a method to get this software via some reasonable mechanism +(electronic transfer via a network or media) as well as making an offer to +supply the source on request. This Copyright notice serves as an offer to +supply the source on on request as well. Instead of this, supplying +acknowledgments of use of this software in either Copyright notices, Manuals, +Publicity and Marketing documents or any documentation provided with any +product containing this software. This License does not apply to any software +that links to the libraries provided by this software (statically or +dynamically), but only to the software provided. + +Please see the COPYING-PLAIN for a plain-english explanation of this notice +and its intent. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..7536cd1 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,2 @@ +12/10/2007 Sthithaprajna Garapaty + * MPDule in CVS diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..54caf7c --- /dev/null +++ b/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..64e9149 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,26 @@ +MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \ + config.sub configure depcomp install-sh ltmain.sh \ + missing module.desktop config.rpath mkinstalldirs + +SUBDIRS = src + +EDJE_FLAGS = -v \ + -id $(top_srcdir)/images + +filesdir = $(datadir) +files_DATA = e-module-empris.edj module.desktop empris.edj + +EXTRA_DIST = module.desktop.in \ + e_modules-mpdule.spec.in \ + e-module-mpdule.edc \ + empris.edc \ + $(wildcard images/*.png) + +%.edj: %.edc + $(EDJE_CC) $(EDJE_FLAGS) $< $@ + +clean-local: + rm -rf e-module-empris.edj empris.edj module.desktop e_modules-empris.spec *~ + +uninstall: + rm -rf $(DESTDIR)$(datadir) diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..187d329 --- /dev/null +++ b/README @@ -0,0 +1,5 @@ +Simple MPD module +Load it into your shelf. Set it to: Able to be Resized, and resize to a good size for best experience. + +To see more than just the artist and title, edit the theme (See comments in the theme for more info). + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..2003c6e --- /dev/null +++ b/autogen.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +rm -rf autom4te.cache +rm -f aclocal.m4 ltmain.sh + +touch README + +#echo "Running autopoint..." ; autopoint -f || : +echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS || exit 1 +echo "Running autoheader..." ; autoheader || exit 1 +echo "Running autoconf..." ; autoconf || exit 1 +echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1 +echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1 + +if [ -z "$NOCONFIGURE" ]; then + ./configure "$@" +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..5d65c00 --- /dev/null +++ b/configure.ac @@ -0,0 +1,65 @@ +dnl Process this file with autoconf to produce a configure script. + +# get rid of that stupid cache mechanism +rm -f config.cache + +AC_INIT(empris, 0.0.1, hannes.janetzek@gmail.com) +AC_PREREQ(2.59) +AC_CONFIG_HEADERS(config.h) +AM_INIT_AUTOMAKE(1.8) + +AC_CANONICAL_BUILD +AC_CANONICAL_HOST + +AC_PROG_CC +AC_HEADER_STDC +AC_HEADER_TIME + +define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl +define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl +AC_PROG_LIBTOOL + +ALL_LINGUAS="" +AC_SUBST(ALL_LINGUAS) + +#AM_GNU_GETTEXT([external]) +#AM_GNU_GETTEXT_VERSION(0.14) + +PKG_CHECK_MODULES(E, [enlightenment]) +release=$(pkg-config --variable=release enlightenment) +MODULE_ARCH="$host_os-$host_cpu-$release" +AC_SUBST(MODULE_ARCH) +AC_DEFINE_UNQUOTED(MODULE_ARCH, "$MODULE_ARCH", "Module architecture") + +uname=`uname` + +# Find edje_cc +PKG_CHECK_MODULES(EDJE, [edje >= 0.5.0]) +AC_ARG_WITH(edje-cc, + AC_HELP_STRING([--with-edje-cc=PATH], [specify a specific path to edje_cc]), + [ + v=$withval; + EDJE_CC=$v + ],[ + EDJE_CC=$(pkg-config --variable=prefix edje)/bin/edje_cc + ] +) +AC_SUBST(EDJE_CC) +AC_MSG_CHECKING([Which edje_cc to use]) +AC_MSG_RESULT(${EDJE_CC}) + +datadir=$(pkg-config --variable=modules enlightenment)/${PACKAGE} + + +AC_ARG_ENABLE(homedir-install, + AS_HELP_STRING([--enable-homedir-install], [Install module in homedir]), + [ datadir="${HOME}/.e/e/modules/${PACKAGE}" ] +) + +AC_OUTPUT([ +Makefile +src/Makefile +e_modules-empris.spec +module.desktop +],[ +]) diff --git a/e-module-empris.edc b/e-module-empris.edc new file mode 100644 index 0000000..6de0ae4 --- /dev/null +++ b/e-module-empris.edc @@ -0,0 +1,32 @@ +images { + image: "module_icon.png" COMP; +} +collections { + group { + name: "icon"; + max: 48 48; + parts { + part { + name: "image"; + type: IMAGE; + mouse_events: 0; + description { + state: "default" 0.00; + visible: 1; + aspect: 1.00 1.00; + rel1 { + relative: 0.00 0.00; + offset: 0 0; + } + rel2 { + relative: 1.00 1.00; + offset: -1 -1; + } + image { + normal: "module_icon.png"; + } + } + } + } + } +} diff --git a/e_modules-empris.spec.in b/e_modules-empris.spec.in new file mode 100644 index 0000000..5cff1c0 --- /dev/null +++ b/e_modules-empris.spec.in @@ -0,0 +1,50 @@ +%define module_name mpdule + +Summary: %{module_name} module for the Enlightenment window manager +Name: e_modules-%{module_name} +Version: @VERSION@ +Release: 0.%(date '+%Y%m%d') +License: BSD +Group: User Interface/Desktops +URL: http://www.enlightenment.org/ +Source: ftp://ftp.enlightenment.org/pub/enlightenment/%{module_name}-%{version}.tar.gz +Packager: %{?_packager:%{_packager}}%{!?_packager:Michael Jennings } +Vendor: %{?_vendorinfo:%{_vendorinfo}}%{!?_vendorinfo:The Enlightenment Project (http://www.enlightenment.org/)} +Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}} +BuildRequires: ecore-devel, evas-devel, esmart-devel, edje-bin +BuildRequires: edje-devel, eet-devel, enlightenment-devel >= 0.16.999 +Requires: enlightenment >= 0.16.999 +BuildRoot: %{_tmppath}/%{name}-%{version}-root + +%description +%{module_name} module for the Enlightenment window manager. + +%prep +%setup -q -n %{module_name}-%{version} + +%build +%{configure} +%{__make} %{?_smp_mflags} %{?mflags} + +%install +%{__make} %{?mflags_install} DESTDIR=$RPM_BUILD_ROOT install +%{find_lang} %{module_name} || true > %{module_name}.lang + +%clean +test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT + +%post +/sbin/ldconfig + +%postun +/sbin/ldconfig + +%files -f %{module_name}.lang +%defattr(-, root, root) +%doc AUTHORS ChangeLog COPYING* INSTALL NEWS README +%if "%{module_name}" == "emu" +%{_bindir}/%{module_name}* +%endif +%{_libdir}/enlightenment/modules/%{module_name}* + +%changelog diff --git a/empris.edc b/empris.edc new file mode 100644 index 0000000..732c7f5 --- /dev/null +++ b/empris.edc @@ -0,0 +1,984 @@ +spectra +{ +} + +color_classes +{ +} + +images +{ +image:"next.png" COMP; +image:"pause.png" COMP; +image:"play.png" COMP; +image:"prev.png" COMP; +image:"stop.png" COMP; +} + +data +{ +} + +styles +{ +} + +/* +Available labels: +empris.status +empris.artist +empris.title +empris.album +empris.track +empris.date +empris.genre +empris.composer +empris.time +empris.file +*/ +collections +{ + group + { + name:"modules/empris/main"; + parts + { + part + { + name:"base"; + type:RECT; + mouse_events:0; + description + { + state:"default" 0.00; + visible:1; + rel1 + { + relative:0.00 0.00; + offset:0 0; + } + rel2 + { + relative:1.00 1.00; + offset:-1 -1; + } + } + } + part + { + name:"item_clip"; + type:RECT; + description + { + state:"default" 0.00; + visible:1; + rel1 + { + relative:0.00 0.00; + offset:0 0; + } + rel2 + { + relative:1.00 1.00; + offset:-1 -1; + } + color:255 255 255 0; + } + description + { + state:"hide" 0.00; + visible:1; + rel1 + { + relative:0.00 -1.00; + offset:0 0; + } + rel2 + { + relative:1.00 0.00; + offset:-1 -1; + } + color:255 255 255 0; + } + } + part + { + name:"controls_clip"; + type:RECT; + description + { + state:"default" 0.00; + visible:1; + rel1 + { + relative:0.00 1.00; + offset:0 0; + } + rel2 + { + relative:1.00 2.00; + offset:-1 -1; + } + color:255 255 255 0; + } + description + { + state:"show" 0.00; + visible:1; + rel1 + { + relative:0.00 0.00; + offset:0 0; + } + rel2 + { + relative:1.00 1.00; + offset:-1 -1; + } + color:255 255 255 0; + } + } + part + { + name:"empris.artist"; + type:TEXT; + effect:OUTLINE_SOFT_SHADOW; + clip_to:"base"; + mouse_events:0; + description + { + state:"default" 0.00; + visible:1; + rel1 + { + relative:0.00 0.00; + offset:0 4; + to:"item_clip"; + } + rel2 + { + relative:1.00 0.50; + offset:-1 -3; + to:"item_clip"; + } + color2:0 0 0 96; + color3:0 0 0 32; + text + { + text:""; + text_class:"empris"; + font:"Sans:style=Mono"; + size:10; + min:1 1; + align:0.50 0.50; + } + } + description + { + state:"hidden" 0.00; + visible:0; + rel1 + { + relative:0.00 0.00; + offset:0 4; + to:"item_clip"; + } + rel2 + { + relative:1.00 0.50; + offset:-1 -3; + to:"item_clip"; + } + color2:0 0 0 96; + color3:0 0 0 32; + text + { + text:""; + text_class:"empris"; + font:"Sans:style=Mono"; + size:10; + min:1 1; + align:0.50 0.50; + } + } + description + { + state:"visible" 0.00; + visible:1; + rel1 + { + relative:0.00 0.00; + offset:0 4; + to:"item_clip"; + } + rel2 + { + relative:1.00 0.50; + offset:-1 -3; + to:"item_clip"; + } + color2:0 0 0 96; + color3:0 0 0 32; + text + { + text:""; + text_class:"empris"; + font:"Sans:style=Mono"; + size:10; + min:1 1; + align:0.50 0.50; + } + } + } + part + { + name:"empris.title"; + type:TEXT; + effect:OUTLINE_SOFT_SHADOW; + clip_to:"base"; + mouse_events:0; + description + { + state:"default" 0.00; + visible:1; + rel1 + { + relative:0.00 0.50; + offset:0 4; + to:"item_clip"; + } + rel2 + { + relative:1.00 1.00; + offset:-1 -3; + to:"item_clip"; + } + color2:0 0 0 96; + color3:0 0 0 32; + text + { + text:""; + text_class:"empris"; + font:"Sans:style=Mono"; + size:9; + min:1 1; + align:0.50 0.50; + } + } + description + { + state:"hidden" 0.00; + visible:0; + rel1 + { + relative:0.00 0.50; + offset:0 4; + to:"item_clip"; + } + rel2 + { + relative:1.00 1.00; + offset:-1 -3; + to:"item_clip"; + } + color2:0 0 0 96; + color3:0 0 0 32; + text + { + text:""; + text_class:"empris"; + font:"Sans:style=Mono"; + size:9; + min:1 1; + align:0.50 0.50; + } + } + description + { + state:"visible" 0.00; + visible:1; + rel1 + { + relative:0.00 0.50; + offset:0 4; + to:"item_clip"; + } + rel2 + { + relative:1.00 1.00; + offset:-1 -3; + to:"item_clip"; + } + color2:0 0 0 96; + color3:0 0 0 32; + text + { + text:""; + text_class:"empris"; + font:"Sans:style=Mono"; + size:9; + min:1 1; + align:0.50 0.50; + } + } + } + part + { + name:"empris.previous"; + type:IMAGE; + mouse_events:1; + repeat_events:1; + description + { + state:"default" 0.0; + visible:1; + aspect:1 1; + align:0.0 0.5; + rel1 + { + relative:0.0 0.0; + offset:0 0; + to:"controls_clip"; + } + rel2 + { + relative:0.0 1.0; + to:"controls_clip"; + } + image + { + normal:"prev.png"; + } + } + } + part + { + name:"empris.play"; + type:IMAGE; + mouse_events:1; + repeat_events:1; + description + { + state:"default" 0.0; + visible:1; + aspect:1 1; + align:0.0 0.5; + rel1 + { + relative:1.0 0.0; + offset:0 0; + to_x:"empris.previous"; + to_y:"controls_clip"; + } + rel2 + { + relative:1.0 1.0; + to_x:"empris.previous"; + to_y:"controls_clip"; + } + image + { + normal:"play.png"; + } + } + } + part + { + name:"empris.pause"; + type:IMAGE; + mouse_events:1; + repeat_events:1; + description + { + state:"default" 0.0; + visible:1; + aspect:1 1; + align:0.0 0.5; + rel1 + { + relative:1.0 0.0; + offset:0 0; + to_x:"empris.play"; + to_y:"controls_clip"; + } + rel2 + { + relative:1.0 1.0; + to_x:"empris.play"; + to_y:"controls_clip"; + } + image + { + normal:"pause.png"; + } + } + } + part + { + name:"empris.stop"; + type:IMAGE; + mouse_events:1; + repeat_events:1; + description + { + state:"default" 0.0; + visible:1; + aspect:1 1; + align:0.0 0.5; + rel1 + { + relative:1.0 0.0; + offset:0 0; + to_x:"empris.pause"; + to_y:"controls_clip"; + } + rel2 + { + relative:1.0 1.0; + to_x:"empris.pause"; + to_y:"controls_clip"; + } + image + { + normal:"stop.png"; + } + } + } + part + { + name:"empris.next"; + type:IMAGE; + mouse_events:1; + repeat_events:1; + description + { + state:"default" 0.0; + visible:1; + aspect:1 1; + align:0.0 0.5; + rel1 + { + relative:1.0 0.0; + offset:0 0; + to_x:"empris.stop"; + to_y:"controls_clip"; + } + rel2 + { + relative:1.0 1.0; + to_x:"empris.stop"; + to_y:"controls_clip"; + } + image + { + normal:"next.png"; + } + } + } + part + { + name:"event_grab"; + type:RECT; + repeat_events:1; + description + { + state:"default" 0.00; + visible:1; + color:0 0 0 0; + rel1 + { + relative:0.00 0.00; + offset:0 0; + } + rel2 + { + relative:1.00 1.00; + offset:-1 -1; + } + } + } + } + programs + { + program + { + name:"show_controls"; + signal:"mouse,in"; + source:"event_grab"; + action:STATE_SET "show" 0.0; + transition:LINEAR 0.1; + target:"controls_clip"; + } + program + { + name:"show_controls2"; + signal:"mouse,in"; + source:"event_grab"; + action:STATE_SET "hide" 0.0; + transition:LINEAR 0.1; + target:"item_clip"; + } + program + { + name:"wait"; + action:STATE_SET "hide" 0.0; + transition:LINEAR 2; + target:"item_clip"; + after:"hide_controls"; + after:"hide_controls2"; + } + program + { + name:"hide_controls"; + signal:"mouse,out"; + source:"event_grab"; + action:STATE_SET "default" 0.0; + transition:LINEAR 0.1; + target:"controls_clip"; + } + program + { + name:"hide_controls2"; + signal:"mouse,out"; + source:"event_grab"; + action:STATE_SET "default" 0.0; + transition:LINEAR 0.1; + target:"item_clip"; + } + program + { + name:"mouse_play"; + signal:"mouse,clicked,1"; + source:"empris.play"; + action:SIGNAL_EMIT "empris,play" ""; + } + program + { + name:"mouse_pause"; + signal:"mouse,clicked,1"; + source:"empris.pause"; + action:SIGNAL_EMIT "empris,pause" ""; + } + program + { + name:"mouse_stop"; + signal:"mouse,clicked,1"; + source:"empris.stop"; + action:SIGNAL_EMIT "empris,stop" ""; + } + program + { + name:"mouse_previous"; + signal:"mouse,clicked,1"; + source:"empris.previous"; + action:SIGNAL_EMIT "empris,previous" ""; + } + program + { + name:"mouse_next"; + signal:"mouse,clicked,1"; + source:"empris.next"; + action:SIGNAL_EMIT "empris,next" ""; + } + } + } + group + { + name:"modules/empris/popup"; + parts + { + part + { + name:"base"; + type:RECT; + mouse_events:0; + description + { + state:"default" 0.00; + visible:1; + min:200 45; + rel1 + { + relative:0.00 0.00; + offset:5 5; + } + rel2 + { + relative:1.00 1.00; + offset:-5 -5; + } + } + } + part + { + name:"labels"; + type:RECT; + mouse_events:0; + description + { + state:"default" 0.00; + visible:1; + rel1 + { + relative:0.00 0.00; + offset:0 0; + to:"base"; + } + rel2 + { + relative:0.25 1.00; + offset:0 0; + to:"base"; + } + color:255 255 255 0; + } + } + part + { + name:"values"; + type:RECT; + mouse_events:0; + description + { + state:"default" 0.00; + visible:1; + rel1 + { + relative:0.25 0.00; + offset:0 0; + to:"base"; + } + rel2 + { + relative:1.00 1.00; + offset:0 0; + to:"base"; + } + color:255 255 255 0; + } + } + part + { + name:"item_clip"; + type:RECT; + description + { + state:"default" 0.00; + visible:1; + min:5 5; + rel1 + { + relative:0.00 0.00; + offset:0 0; + } + rel2 + { + relative:1.00 1.00; + offset:-1 -1; + } + color:255 255 255 0; + } + } + part + { + name:"empris.artist_label"; + type:TEXT; + effect:SHADOW; + clip_to:"base"; + description + { + state:"default" 0.00; + visible:1; + align:0.00 0.50; + fixed:1 1; + rel1 + { + relative:-0.00 0.00; + offset:0 0; + to:"labels"; + } + rel2 + { + relative:1.00 0.00; + offset:0 16; + to:"labels"; + } + color:0 0 0 255; + color3:255 255 255 128; + text + { + text:"Artist:"; + text_class:"empris"; + font:"Sans:style=Mono"; + size:10; + min:1 1; + align:1.0 0.50; + } + } + } + part + { + name:"empris.title_label"; + type:TEXT; + effect:SHADOW; + clip_to:"base"; + description + { + state:"default" 0.00; + visible:1; + align:0.00 0.50; + rel1 + { + relative:0.00 1.00; + offset:0 0; + to_x:"labels"; + to_y:"empris.artist_label"; + } + rel2 + { + relative:1.00 1.00; + offset:0 12; + to_x:"labels"; + to_y:"empris.artist_label"; + } + color:0 0 0 255; + color3:255 255 255 128; + text + { + text:"Title:"; + text_class:"empris"; + font:"Sans:style=Mono"; + size:10; + min:1 1; + align:1.0 0.50; + } + } + } + part + { + name:"empris.album_label"; + type:TEXT; + mouse_events:0; + effect:SHADOW; + clip_to:"base"; + description + { + state:"default" 0.00; + visible:1; + align:0.00 0.50; + rel1 + { + relative:0.00 1.00; + offset:0 0; + to_x:"labels"; + to_y:"empris.title_label"; + } + rel2 + { + relative:1.00 1.00; + offset:0 12; + to_x:"labels"; + to_y:"empris.title_label"; + } + color:0 0 0 255; + color3:255 255 255 128; + text + { + text:"Album:"; + text_class:"empris"; + font:"Sans:style=Mono"; + size:10; + min:1 1; + align:1.0 0.50; + } + } + } + part + { + name:"empris.genre_label"; + type:TEXT; + mouse_events:0; + effect:SHADOW; + clip_to:"base"; + description + { + state:"default" 0.00; + visible:1; + align:0.00 0.50; + rel1 + { + relative:0.00 1.00; + offset:0 0; + to_x:"labels"; + to_y:"empris.album_label"; + } + rel2 + { + relative:1.00 1.00; + offset:0 12; + to_x:"labels"; + to_y:"empris.album_label"; + } + color:0 0 0 255; + color3:255 255 255 128; + text + { + text:"Genre:"; + text_class:"empris"; + font:"Sans:style=Mono"; + size:10; + min:1 1; + align:1.0 0.50; + } + } + } + part + { + name:"empris.artist"; + type:TEXT; + effect:NONE; + clip_to:"base"; + description + { + state:"default" 0.00; + visible:1; + align:0.00 0.50; + rel1 + { + relative:0.00 0.00; + offset:0 0; + to_x:"values"; + to_y:"empris.artist_label"; + } + rel2 + { + relative:1.00 1.00; + to_x:"values"; + to_y:"empris.artist_label"; + } + color:0 0 0 255; + text + { + text:""; + text_class:"empris"; + font:"Sans:style=Bold"; + size:10; + min:1 1; + align:0.0 0.50; + } + } + } + part + { + name:"empris.title"; + type:TEXT; + effect:NONE; + clip_to:"base"; + description + { + state:"default" 0.00; + visible:1; + align:0.00 0.50; + rel1 + { + relative:0.00 0.00; + offset:0 0; + to_x:"values"; + to_y:"empris.title_label"; + } + rel2 + { + relative:1.00 1.00; + to_x:"values"; + to_y:"empris.title_label"; + } + color:0 0 0 255; + text + { + text:""; + text_class:"empris"; + font:"Sans:style=Bold"; + size:10; + min:1 1; + align:0.0 0.50; + } + } + } + part + { + name:"empris.album"; + type:TEXT; + effect:NONE; + clip_to:"base"; + description + { + state:"default" 0.00; + visible:1; + align:0.00 0.50; + rel1 + { + relative:0.00 0.00; + offset:0 0; + to_x:"values"; + to_y:"empris.album_label"; + } + rel2 + { + relative:1.00 1.00; + to_x:"values"; + to_y:"empris.album_label"; + } + color:0 0 0 255; + text + { + text:""; + text_class:"empris"; + font:"Sans:style=Bold"; + size:10; + min:1 1; + align:0.0 0.50; + } + } + } + part + { + name:"empris.genre"; + type:TEXT; + effect:NONE; + clip_to:"base"; + description + { + state:"default" 0.00; + visible:1; + align:0.00 0.50; + rel1 + { + relative:0.00 0.00; + offset:0 0; + to_x:"values"; + to_y:"empris.genre_label"; + } + rel2 + { + relative:1.00 1.00; + to_x:"values"; + to_y:"empris.genre_label"; + } + color:0 0 0 255; + text + { + text:""; + text_class:"empris"; + font:"Sans:style=Bold"; + size:10; + min:1 1; + align:0.0 0.50; + } + } + } + } + programs + { + } + } +} diff --git a/images/module_icon.png b/images/module_icon.png new file mode 100644 index 0000000..2cb83e4 Binary files /dev/null and b/images/module_icon.png differ diff --git a/images/next.png b/images/next.png new file mode 100644 index 0000000..ef1de3d Binary files /dev/null and b/images/next.png differ diff --git a/images/pause.png b/images/pause.png new file mode 100644 index 0000000..900152e Binary files /dev/null and b/images/pause.png differ diff --git a/images/play.png b/images/play.png new file mode 100644 index 0000000..0ea9929 Binary files /dev/null and b/images/play.png differ diff --git a/images/prev.png b/images/prev.png new file mode 100644 index 0000000..8218387 Binary files /dev/null and b/images/prev.png differ diff --git a/images/stop.png b/images/stop.png new file mode 100644 index 0000000..027a7c7 Binary files /dev/null and b/images/stop.png differ diff --git a/module.desktop.in b/module.desktop.in new file mode 100644 index 0000000..c1a29a9 --- /dev/null +++ b/module.desktop.in @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Link +Name=EMpris +Icon=e-module-empris +Comment=Control MPRIS supporting music player like Amarok, Audacious, xmms2, vlc and others + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..f87b6b5 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,19 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = -I. \ + -I$(top_srcdir) \ + -I$(includedir) \ + @E_CFLAGS@ + +pkgdir = $(datadir)/$(MODULE_ARCH) +pkg_LTLIBRARIES = module.la +module_la_SOURCES = e_mod_main.c \ + e_mod_main.h \ + e_mod_config.c + +module_la_LIBADD = @E_LIBS@ +module_la_LDFLAGS = -module -avoid-version +module_la_DEPENDENCIES = $(top_builddir)/config.h + +clean-local: + rm -rf *~ diff --git a/src/e_mod_config.c b/src/e_mod_config.c new file mode 100644 index 0000000..ad6d897 --- /dev/null +++ b/src/e_mod_config.c @@ -0,0 +1,114 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include +#include "e_mod_main.h" + +struct _E_Config_Dialog_Data +{ + char *player; + int show_popup; +}; + +/* Protos */ +static void *_create_data (E_Config_Dialog * cfd); +static void _free_data (E_Config_Dialog * cfd, E_Config_Dialog_Data * cfdata); +static Evas_Object *_basic_create_widgets (E_Config_Dialog * cfd, Evas * evas, + E_Config_Dialog_Data * cfdata); +static int _basic_apply_data (E_Config_Dialog * cfd, + E_Config_Dialog_Data * cfdata); + +void +_config_empris_module (Config_Item * ci) +{ + E_Config_Dialog *cfd; + E_Config_Dialog_View *v; + E_Container *con; + char buf[4096]; + + v = E_NEW (E_Config_Dialog_View, 1); + + v->create_cfdata = _create_data; + v->free_cfdata = _free_data; + v->basic.apply_cfdata = _basic_apply_data; + v->basic.create_widgets = _basic_create_widgets; + + snprintf (buf, sizeof (buf), "%s/e-module-empris.edj", + e_module_dir_get (empris_config->module)); + con = e_container_current_get (e_manager_current_get ()); + cfd = + e_config_dialog_new (con, D_ ("Empris Configuration"), "Empris", + "_e_modules_empris_config_dialog", buf, 0, v, ci); + empris_config->config_dialog = cfd; +} + +static void +_fill_data (Config_Item * ci, E_Config_Dialog_Data * cfdata) +{ + char buf[128]; + + cfdata->player = strdup (ci->player); + cfdata->show_popup = ci->show_popup; +} + +static void * +_create_data (E_Config_Dialog * cfd) +{ + E_Config_Dialog_Data *cfdata; + Config_Item *ci; + + ci = cfd->data; + cfdata = E_NEW (E_Config_Dialog_Data, 1); + + _fill_data (ci, cfdata); + return cfdata; +} + +static void +_free_data (E_Config_Dialog * cfd, E_Config_Dialog_Data * cfdata) +{ + if (!empris_config) + return; + empris_config->config_dialog = NULL; + free (cfdata->player); + E_FREE (cfdata); +} + +static Evas_Object * +_basic_create_widgets (E_Config_Dialog * cfd, Evas * evas, + E_Config_Dialog_Data * cfdata) +{ + Evas_Object *o, *of, *ob, *player_entry; + + o = e_widget_list_add (evas, 0, 0); + + of = e_widget_frametable_add (evas, D_ ("Configuration"), 1); + + ob = e_widget_label_add (evas, D_ ("Player:")); + e_widget_frametable_object_append (of, ob, 0, 0, 1, 1, 1, 0, 1, 0); + + player_entry = e_widget_entry_add (evas, &cfdata->player, NULL, NULL, NULL); + e_widget_frametable_object_append (of, player_entry, 0, 1, 1, 1, 1, 0, 1, 0); + e_widget_size_min_set (player_entry, 150, 1); + + ob = e_widget_check_add(evas, D_("Show Popup:"), &(cfdata->show_popup)); + e_widget_frametable_object_append(of, ob, 0, 4, 1, 1, 1, 0, 1, 0); + + e_widget_list_object_append (o, of, 1, 1, 0.5); + return o; +} + +static int +_basic_apply_data (E_Config_Dialog * cfd, E_Config_Dialog_Data * cfdata) +{ + Config_Item *ci; + + ci = cfd->data; + if (ci->player) + eina_stringshare_del (ci->player); + ci->player = eina_stringshare_add (cfdata->player); + ci->show_popup = cfdata->show_popup; + e_config_save_queue (); + _empris_config_updated (ci); + return 1; +} diff --git a/src/e_mod_main.c b/src/e_mod_main.c new file mode 100644 index 0000000..91909bd --- /dev/null +++ b/src/e_mod_main.c @@ -0,0 +1,1057 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include +#include "e_mod_main.h" +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#define MAX_SONG_LENGTH 255 + +typedef struct _Instance Instance; +struct _Instance +{ + E_Gadcon_Client *gcc; + Evas_Object *empris; + Evas_Object *o_popup; + Config_Item *ci; + E_Gadcon_Popup *popup; + + /* E_DBus_Signal_Handler *cb_tracklist_change = NULL; */ + E_DBus_Signal_Handler *cb_player_track_change; + E_DBus_Signal_Handler *cb_player_status_change; +}; + +/* Func Proto Requirements for Gadcon */ +static E_Gadcon_Client *_gc_init (E_Gadcon * gc, const char *name, + const char *id, const char *style); +static void _gc_shutdown (E_Gadcon_Client * gcc); +static void _gc_orient (E_Gadcon_Client * gcc, E_Gadcon_Orient orient); +static char *_gc_label (E_Gadcon_Client_Class *client_class); +static Evas_Object *_gc_icon (E_Gadcon_Client_Class *client_class, Evas * evas); +static const char *_gc_id_new (E_Gadcon_Client_Class *client_class); + +/* Module Protos */ +static void _empris_cb_mouse_down (void *data, Evas * e, Evas_Object * obj, void *event_info); +static void _empris_cb_mouse_in (void *data, Evas * e, Evas_Object * obj, void *event_info); +static void _empris_cb_mouse_out (void *data, Evas * e, Evas_Object * obj, void *event_info); +static void _empris_menu_cb_configure (void *data, E_Menu * m, E_Menu_Item * mi); +static void _empris_menu_cb_post (void *data, E_Menu * m); +static void _empris_cb_play (void *data, Evas_Object * obj, const char *emission, const char *source); +static void _empris_cb_stop (void *data, Evas_Object * obj, const char *emission, const char *source); +static void _empris_cb_pause (void *data, Evas_Object * obj, const char *emission, const char *source); +static void _empris_cb_next (void *data, Evas_Object * obj, const char *emission, const char *source); +static void _empris_cb_previous (void *data, Evas_Object * obj, const char *emission, const char *source); +static Config_Item *_empris_config_item_get (const char *id); + +static void _set_status(Instance *inst, DBusMessage *msg); +static void _dbus_cb_tracklist_metadata(void *data, DBusMessage *reply, DBusError *error); +static void _dbus_cb_get_status(void *data, DBusMessage *reply, DBusError *error); +static void _dbus_cb_track_change(void *data, DBusMessage *msg); +static void _dbus_cb_current_track(void *data, DBusMessage *reply, DBusError *error); +static void _dbus_cb_list_names(void *data, DBusMessage *msg, DBusError *err); +static void _dbus_cb_name_owner_changed(void *data, DBusMessage *msg); +static void _dbus_cb_status_change(void *data, DBusMessage *msg); +static DBusPendingCall *_dbus_send_msg(const char *path, const char *method, E_DBus_Method_Return_Cb _cb, void *data); + +static char * _util_unescape(const char *string, int length); + + +static E_Config_DD *conf_edd = NULL; +static E_Config_DD *conf_item_edd = NULL; + + +static E_DBus_Connection *conn = NULL; +static DBusPendingCall *pending_get_name_owner = NULL; +static E_DBus_Signal_Handler *cb_name_owner_changed = NULL; +static const char *bus_name = NULL; +static const char mpris_interface[] = "org.freedesktop.MediaPlayer"; +static const char fdo_bus_name[] = "org.freedesktop.DBus"; +static const char fdo_interface[] = "org.freedesktop.DBus"; +static const char fdo_path[] = "/org/freedesktop/DBus"; + +static Eina_List *players = NULL; +static Eina_Bool active = EINA_FALSE; + +Config *empris_config = NULL; + +/* Define the class and gadcon functions this module provides */ +static const E_Gadcon_Client_Class _gc_class = { + GADCON_CLIENT_CLASS_VERSION, + "empris", {_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, + _gc_id_new, NULL, e_gadcon_site_is_not_toolbar}, + E_GADCON_CLIENT_STYLE_PLAIN +}; + +static void _empris_popup_destroy (Instance * inst); +static void _empris_popup_create (Instance * inst, const char *dir); + + +static E_Gadcon_Client * +_gc_init (E_Gadcon * gc, const char *name, const char *id, const char *style) +{ + Evas_Object *o; + E_Gadcon_Client *gcc; + Evas *evas; + Instance *inst; + char buf[4096]; + + inst = E_NEW (Instance, 1); + + inst->ci = _empris_config_item_get (id); + if (!inst->ci->id) + inst->ci->id = eina_stringshare_add (id); + + o = edje_object_add (gc->evas); + snprintf (buf, sizeof (buf), "%s/empris.edj", + e_module_dir_get (empris_config->module)); + if (!e_theme_edje_object_set + (o, "base/theme/modules/empris", "modules/empris/main")) + edje_object_file_set (o, buf, "modules/empris/main"); + evas_object_show (o); + + gcc = e_gadcon_client_new (gc, name, id, style, o); + gcc->data = inst; + inst->gcc = gcc; + inst->empris = o; + + _empris_popup_create(inst, buf); + + evas_object_event_callback_add (o, EVAS_CALLBACK_MOUSE_DOWN, + _empris_cb_mouse_down, inst); + evas_object_event_callback_add (inst->empris, EVAS_CALLBACK_MOUSE_IN, + _empris_cb_mouse_in, inst); + evas_object_event_callback_add (inst->empris, EVAS_CALLBACK_MOUSE_OUT, + _empris_cb_mouse_out, inst); + edje_object_signal_callback_add (o, "empris,play", "", _empris_cb_play, + inst); + edje_object_signal_callback_add (o, "empris,stop", "", _empris_cb_stop, + inst); + edje_object_signal_callback_add (o, "empris,pause", "", _empris_cb_pause, + inst); + edje_object_signal_callback_add (o, "empris,next", "", _empris_cb_next, + inst); + edje_object_signal_callback_add (o, "empris,previous", "", + _empris_cb_previous, inst); + + inst->cb_player_track_change = e_dbus_signal_handler_add + (conn, bus_name, "/Player", mpris_interface, "TrackChange", + _dbus_cb_track_change, inst); + + inst->cb_player_status_change = e_dbus_signal_handler_add + (conn, bus_name, "/Player", mpris_interface, "StatusChange", + _dbus_cb_status_change, inst); + + _dbus_send_msg("/TrackList", "GetCurrentTrack", _dbus_cb_current_track, inst); + + empris_config->instances = eina_list_append (empris_config->instances, inst); + return gcc; +} + + + +static void +_gc_shutdown (E_Gadcon_Client * gcc) +{ + Instance *inst; + + inst = gcc->data; + + if (inst->cb_player_track_change) + e_dbus_signal_handler_del(conn, inst->cb_player_track_change); + if (inst->cb_player_status_change) + e_dbus_signal_handler_del(conn, inst->cb_player_status_change); + + empris_config->instances = eina_list_remove (empris_config->instances, inst); + + evas_object_event_callback_del (inst->empris, EVAS_CALLBACK_MOUSE_DOWN, + _empris_cb_mouse_down); + evas_object_event_callback_del (inst->empris, EVAS_CALLBACK_MOUSE_IN, + _empris_cb_mouse_in); + evas_object_event_callback_del (inst->empris, EVAS_CALLBACK_MOUSE_OUT, + _empris_cb_mouse_out); + _empris_popup_destroy (inst); + evas_object_del (inst->empris); + free (inst); + inst = NULL; +} + +static void +_gc_orient (E_Gadcon_Client * gcc, E_Gadcon_Orient orient) +{ + Instance *inst; + Evas_Coord mw, mh; + + inst = gcc->data; + edje_object_size_min_calc (inst->empris, &mw, &mh); + e_gadcon_client_min_size_set (gcc, mw, mh); +} + +static char * +_gc_label (E_Gadcon_Client_Class *client_class) +{ + return D_ ("Empris"); +} + +static Evas_Object * +_gc_icon (E_Gadcon_Client_Class *client_class, Evas * evas) +{ + Evas_Object *o; + char buf[4096]; + + o = edje_object_add (evas); + snprintf (buf, sizeof (buf), "%s/e-module-empris.edj", + e_module_dir_get (empris_config->module)); + edje_object_file_set (o, buf, "icon"); + return o; +} + +static const char * +_gc_id_new (E_Gadcon_Client_Class *client_class) +{ + Config_Item *ci; + + ci = _empris_config_item_get (NULL); + return ci->id; +} + +static void +_empris_cb_mouse_down (void *data, Evas * e, Evas_Object * obj, + void *event_info) +{ + Instance *inst; + Evas_Event_Mouse_Down *ev; + + inst = data; + ev = event_info; + if ((ev->button == 3) && (!empris_config->menu)) + { + E_Menu *mn; + E_Menu_Item *mi; + int x, y, w, h; + + mn = e_menu_new (); + e_menu_post_deactivate_callback_set (mn, _empris_menu_cb_post, inst); + empris_config->menu = mn; + + mi = e_menu_item_new (mn); + e_menu_item_label_set (mi, D_ ("Configuration")); + e_util_menu_item_theme_icon_set(mi, "preferences-system"); + e_menu_item_callback_set (mi, _empris_menu_cb_configure, inst); + + mi = e_menu_item_new (mn); + e_menu_item_separator_set (mi, 1); + + e_gadcon_client_util_menu_items_append (inst->gcc, mn, 0); + e_gadcon_canvas_zone_geometry_get (inst->gcc->gadcon, &x, &y, &w, &h); + e_menu_activate_mouse (mn, + e_util_zone_current_get (e_manager_current_get + ()), x + ev->output.x, + y + ev->output.y, 1, 1, + E_MENU_POP_DIRECTION_DOWN, ev->timestamp); + evas_event_feed_mouse_up (inst->gcc->gadcon->evas, ev->button, + EVAS_BUTTON_NONE, ev->timestamp, NULL); + } + else if (ev->button == 1) + { + //e_gadcon_popup_toggle_pinned(inst->popup); + } +} + + +static void +_empris_cb_mouse_in (void *data, Evas * e, Evas_Object * obj, + void *event_info) +{ + Instance *inst; + E_Gadcon_Popup *popup; + + if ((!(inst = data)) || (!inst->ci->show_popup)) + return; + popup = inst->popup; + e_gadcon_popup_show (inst->popup); +} + +static void +_empris_cb_mouse_out (void *data, Evas * e, Evas_Object * obj, + void *event_info) +{ + Instance *inst; + E_Gadcon_Popup *popup; + + if ((!(inst = data)) || ((!inst->ci->show_popup) && (inst->popup))) + return; + popup = inst->popup; + e_gadcon_popup_hide (inst->popup); +} + +static void +_empris_menu_cb_post (void *data, E_Menu * m) +{ + if (!empris_config->menu) + return; + e_object_del (E_OBJECT (empris_config->menu)); + empris_config->menu = NULL; +} + +static void +_empris_menu_cb_configure (void *data, E_Menu * m, E_Menu_Item * mi) +{ + Instance *inst; + + inst = data; + _config_empris_module (inst->ci); +} + +void +_empris_config_updated (Config_Item * ci) +{ + Eina_List *l; + + if (!empris_config) + return; + for (l = empris_config->instances; l; l = l->next) + { + Instance *inst; + + inst = l->data; + if (inst->ci != ci) + continue; + + /* TODO choose player */ + + if (inst->ci->show_popup) + { + if (!inst->popup) + { + _empris_popup_create(inst, NULL); + } + } + else + { + if (inst->popup) + { + _empris_popup_destroy(inst); + } + if (inst->o_popup) + { + evas_object_del(inst->o_popup); + } + } + break; + } +} + +static void +_empris_cb_play (void *data, Evas_Object * obj, const char *emission, + const char *source) +{ + _dbus_send_msg("/Player", "Play", NULL, NULL); +} + +static void +_empris_cb_previous (void *data, Evas_Object * obj, const char *emission, + const char *source) +{ + _dbus_send_msg("/Player", "Prev", NULL, NULL); +} + +static void +_empris_cb_next (void *data, Evas_Object * obj, const char *emission, + const char *source) +{ + _dbus_send_msg("/Player", "Next", NULL, NULL); +} + +static void +_empris_cb_stop (void *data, Evas_Object * obj, const char *emission, + const char *source) +{ + _dbus_send_msg("/Player", "Stop", NULL, NULL); +} + +static void +_empris_cb_pause (void *data, Evas_Object * obj, const char *emission, + const char *source) +{ + _dbus_send_msg("/Player", "Pause", NULL, NULL); +} + +static Config_Item * +_empris_config_item_get (const char *id) +{ + Eina_List *l; + Config_Item *ci; + char buf[128]; + + + if (!id) + { + int num = 0; + + /* Create id */ + if (empris_config->items) + { + const char *p; + ci = eina_list_last (empris_config->items)->data; + p = strrchr (ci->id, '.'); + if (p) + num = atoi (p + 1) + 1; + } + snprintf (buf, sizeof (buf), "%s.%d", _gc_class.name, num); + id = buf; + } + else + { + for (l = empris_config->items; l; l = l->next) + { + ci = l->data; + if (!ci->id) + continue; + if (!strcmp (ci->id, id)) + return ci; + } + } + + ci = E_NEW (Config_Item, 1); + ci->id = eina_stringshare_add (id); + ci->player = eina_stringshare_add (""); + ci->show_popup = 1; + + empris_config->items = eina_list_append (empris_config->items, ci); + return ci; +} + +EAPI E_Module_Api e_modapi = { + E_MODULE_API_VERSION, + "Empris" +}; + +EAPI void * +e_modapi_init (E_Module * m) +{ + char buf[4096]; + + snprintf (buf, sizeof (buf), "%s/locale", e_module_dir_get (m)); + bindtextdomain (PACKAGE, buf); + bind_textdomain_codeset (PACKAGE, "UTF-8"); + + conf_item_edd = E_CONFIG_DD_NEW ("Empris_Config_Item", Config_Item); +#undef T +#undef D +#define T Config_Item +#define D conf_item_edd + E_CONFIG_VAL (D, T, id, STR); + E_CONFIG_VAL (D, T, player, STR); + E_CONFIG_VAL (D, T, show_popup, UCHAR); + + conf_edd = E_CONFIG_DD_NEW ("Empris_Config", Config); +#undef T +#undef D +#define T Config +#define D conf_edd + E_CONFIG_LIST (D, T, items, conf_item_edd); + + empris_config = e_config_domain_load ("module.empris", conf_edd); + if (!empris_config) + { + Config_Item *ci; + + empris_config = E_NEW (Config, 1); + + ci = E_NEW (Config_Item, 1); + ci->id = eina_stringshare_add ("0"); + ci->player = eina_stringshare_add (""); + ci->show_popup = 1; + + empris_config->items = eina_list_append (empris_config->items, ci); + } + empris_config->module = m; + + conn = e_dbus_bus_get(DBUS_BUS_SESSION); + + if (!conn) return NULL; + + cb_name_owner_changed = e_dbus_signal_handler_add + (conn, fdo_bus_name, fdo_path, fdo_interface, "NameOwnerChanged", + _dbus_cb_name_owner_changed, NULL); + + e_dbus_list_names(conn, _dbus_cb_list_names, NULL); + + e_gadcon_provider_register (&_gc_class); + + e_module_delayed_set(m, 1); + + return m; +} + +EAPI int +e_modapi_shutdown (E_Module * m) +{ + char *player; + + empris_config->module = NULL; + e_gadcon_provider_unregister (&_gc_class); + + if (conn) + { + if (cb_name_owner_changed) e_dbus_signal_handler_del(conn, cb_name_owner_changed); + e_dbus_connection_close(conn); + } + + EINA_LIST_FREE(players, player) + eina_stringshare_del(player); + + if (empris_config->config_dialog) + e_object_del (E_OBJECT (empris_config->config_dialog)); + if (empris_config->menu) + { + e_menu_post_deactivate_callback_set (empris_config->menu, NULL, NULL); + e_object_del (E_OBJECT (empris_config->menu)); + empris_config->menu = NULL; + } + + while (empris_config->items) + { + Config_Item *ci; + + ci = empris_config->items->data; + empris_config->items = + eina_list_remove_list (empris_config->items, empris_config->items); + if (ci->id) + eina_stringshare_del (ci->id); + free (ci); + ci = NULL; + } + + free (empris_config); + empris_config = NULL; + E_CONFIG_DD_FREE (conf_item_edd); + E_CONFIG_DD_FREE (conf_edd); + return 1; +} + +EAPI int +e_modapi_save (E_Module * m) +{ + e_config_domain_save ("module.empris", conf_edd, empris_config); + return 1; +} + +static void +_empris_popup_destroy (Instance * inst) +{ + if (!inst->popup) + return; + e_object_del (E_OBJECT (inst->popup)); +} + +static void +_empris_popup_create (Instance * inst, const char *dir) +{ + Evas *evas; + Evas_Object *o_popup; + char buf[4096]; + + if (inst->ci->show_popup) + { + inst->popup = e_gadcon_popup_new (inst->gcc); + evas = inst->popup->win->evas; + o_popup = edje_object_add (evas); + if (!e_theme_edje_object_set + (o_popup, "base/theme/modules/empris", "modules/empris/popup")) + { + if (dir) + { + edje_object_file_set (o_popup, dir, "modules/empris/popup"); + } + else + { + snprintf(buf, sizeof(buf), "%s/empris.edj", + e_module_dir_get(empris_config->module)); + edje_object_file_set(o_popup, buf, "modules/empris/popup"); + } + } + evas_object_show (o_popup); + e_gadcon_popup_content_set (inst->popup, o_popup); + edje_object_size_min_calc (o_popup, NULL, NULL); + inst->o_popup = o_popup; + edje_object_signal_callback_add (o_popup, "empris,play", "", + _empris_cb_play, inst); + edje_object_signal_callback_add (o_popup, "empris,stop", "", + _empris_cb_stop, inst); + edje_object_signal_callback_add (o_popup, "empris,pause", "", + _empris_cb_pause, inst); + edje_object_signal_callback_add (o_popup, "empris,next", "", + _empris_cb_next, inst); + edje_object_signal_callback_add (o_popup, "empris,previous", "", + _empris_cb_previous, inst); + } + else + { + inst->popup = NULL; + inst->o_popup = NULL; + } +} + + +static int +_dbus_check_msg(DBusMessage *reply, DBusError *error) +{ + if (error && dbus_error_is_set(error)) + { + printf("Error: %s - %s\n", error->name, error->message); + return 0; + } + return (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN); +} + +static DBusPendingCall * +_dbus_send_msg(const char *path, const char *method, + E_DBus_Method_Return_Cb _cb, void *data) +{ + DBusMessage *msg; + DBusPendingCall *pnd; + + if (!active) return NULL; + + msg = dbus_message_new_method_call(bus_name, path, + mpris_interface, + method); + + pnd = e_dbus_message_send(conn, msg, _cb, -1, data); + dbus_message_unref(msg); + + return pnd; +} + +static DBusPendingCall * +_dbus_send_msg_int(const char *path, const char *method, + E_DBus_Method_Return_Cb _cb, void *data, int num) +{ + DBusMessage *msg; + DBusPendingCall *pnd; + + if (!active) return NULL; + + msg = dbus_message_new_method_call(bus_name, path, + mpris_interface, + method); + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &num, + DBUS_TYPE_INVALID); + + pnd = e_dbus_message_send(conn, msg, _cb, -1, data); + dbus_message_unref(msg); + + return pnd; +} + +static void +_dbus_cb_current_track(void *data, DBusMessage *reply, DBusError *error) +{ + Instance *inst = data; + DBusMessage *msg; + int num; + + printf("cb cur track\n"); + + if (!_dbus_check_msg(reply, error)) return; + + dbus_message_get_args(reply, error, + DBUS_TYPE_INT32, (dbus_int32_t*) &(num), + DBUS_TYPE_INVALID); + + /* XXX inst->pnd*/ + printf("cb current track %d\n", num); + + _dbus_send_msg_int("/TrackList", "GetMetadata", + _dbus_cb_tracklist_metadata, inst, num); + +} + +static void +_dbus_cb_status_change(void *data, DBusMessage *msg) +{ + DBusMessageIter iter, array; + + dbus_message_iter_init(msg, &iter); + + if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRUCT) + { + _set_status(data, msg); + } + else if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_INT32) + { + /* XXX audacious.. */ + _dbus_send_msg("/Player", "GetStatus", _dbus_cb_get_status, data); + } +} + +static void +_dbus_cb_track_change(void *data, DBusMessage *msg) +{ + _dbus_cb_tracklist_metadata(data, msg, NULL); +} + +static void +_dbus_cb_tracklist_metadata(void *data, DBusMessage *reply, DBusError *error) +{ + DBusMessageIter array, item, iter, iter_val; + Instance *inst = data; + int type, cnt = 0; + char *key, *tmp, *location = NULL; + int title = 0; + Evas_Object *empris = inst->empris; + Evas_Object *o_popup = inst->o_popup; + + printf("cb metadata\n"); + + if (error) + { + if (!_dbus_check_msg(reply, error)) + { + printf("dbus garbage!\n"); + goto error; + } + } + + edje_object_part_text_set (empris, "empris.artist", ""); + edje_object_part_text_set (o_popup, "empris.artist", ""); + + edje_object_part_text_set (empris, "empris.title", ""); + edje_object_part_text_set (o_popup, "empris.title", ""); + + edje_object_part_text_set (empris, "empris.album", ""); + edje_object_part_text_set (o_popup, "empris.album", ""); + + + dbus_message_iter_init(reply, &array); + if(dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_ARRAY) + { + dbus_message_iter_recurse(&array, &item); + + while(dbus_message_iter_get_arg_type(&item) == DBUS_TYPE_DICT_ENTRY) + { + dbus_message_iter_recurse(&item, &iter); + if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic(&iter, &key); + } + else + { + printf("not string{n"); + goto error; + } + + dbus_message_iter_next(&iter); + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) + { + printf("not variant\n"); + goto error; + } + + if (!strcmp(key, "artist")) + { + dbus_message_iter_recurse (&iter, &iter_val); + dbus_message_iter_get_basic (&iter_val, &tmp); + if (tmp && tmp[0]) + { + edje_object_part_text_set (empris, "empris.artist", tmp); + edje_object_part_text_set (o_popup, "empris.artist", tmp); + } + } + else if (!strcmp(key, "title")) + { + dbus_message_iter_recurse (&iter, &iter_val); + dbus_message_iter_get_basic (&iter_val, &tmp); + if (tmp && tmp[0]) + { + edje_object_part_text_set (empris, "empris.title", tmp); + edje_object_part_text_set (o_popup, "empris.title", tmp); + title = 1; + } + } + else if (!strcmp(key, "location")) + { + dbus_message_iter_recurse (&iter, &iter_val); + dbus_message_iter_get_basic (&iter_val, &tmp); + if (tmp && tmp[0]) + { + location = strdup(tmp); + } + } + else if (!strcmp(key, "album")) + { + dbus_message_iter_recurse (&iter, &iter_val); + dbus_message_iter_get_basic (&iter_val, &tmp); + if (tmp && tmp[0]) + { + edje_object_part_text_set (empris, "empris.album", tmp); + edje_object_part_text_set (o_popup, "empris.album", tmp); + } + } + /* else if (!strcmp(key, "mtime")) + * { + * dbus_message_iter_recurse (&iter, &iter_val); + * dbus_message_iter_get_basic (&iter_val, &(t->length)); + * } */ + dbus_message_iter_next(&item); + } + } + + if (!title && location) + { + char *tmp = _util_unescape(ecore_file_file_get(location), 0); + + if (tmp) + { + edje_object_part_text_set (empris, "empris.title", tmp); + edje_object_part_text_set (o_popup, "empris.title", tmp); + free(tmp); + } + free(location); + } + + error: + return; +} + + +static void +_set_status(Instance *inst, DBusMessage *msg) +{ + DBusMessageIter iter, array; + int status; + + dbus_message_iter_init(msg, &iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRUCT) + { + edje_object_part_text_set (inst->empris, "empris.status", + D_ ("Unknown")); + edje_object_part_text_set (inst->o_popup, "empris.status", + D_ ("Unknown")); + + printf("no dbus struct\n"); + return; + } + + dbus_message_iter_recurse(&iter, &array); + dbus_message_iter_get_basic(&array, &status); + /* dbus_message_iter_next(&array); */ + /* dbus_message_iter_get_basic(&array, &(p->status.random)); + * dbus_message_iter_next(&array); + * dbus_message_iter_get_basic(&array, &(p->status.repeat)); + * dbus_message_iter_next(&array); + * dbus_message_iter_get_basic(&array, &(p->status.loop)); + * DBG("status %d", p->status.playing); */ + + if (status == 0) + { + edje_object_part_text_set (inst->empris, "empris.status", + D_ ("Stopped")); + edje_object_part_text_set (inst->o_popup, "empris.status", + D_ ("Stopped")); + } + else if (status == 2) + { + edje_object_part_text_set (inst->empris, "empris.status", + D_ ("Playing")); + edje_object_part_text_set (inst->o_popup, "empris.status", + D_ ("Playing")); + } + else if (status == 1) + { + edje_object_part_text_set (inst->empris, "empris.status", + D_ ("Paused")); + edje_object_part_text_set (inst->o_popup, "empris.status", + D_ ("Paused")); + } + else + { + edje_object_part_text_set (inst->empris, "empris.status", + D_ ("Unknown")); + edje_object_part_text_set (inst->o_popup, "empris.status", + D_ ("Unknown")); + } +} + +static void +_dbus_cb_get_status(void *data, DBusMessage *reply, DBusError *error) +{ + if (!_dbus_check_msg(reply, error)) return; + + _set_status(data, reply); +} + +static void +_dbus_cb_name_owner_changed(void *data, DBusMessage *msg) +{ + DBusError err; + Eina_List *l; + const char *tmp; + const char *name, *from, *to; + + if (!conn) return; + + dbus_error_init(&err); + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &from, + DBUS_TYPE_STRING, &to, + DBUS_TYPE_INVALID)) + { + printf("could not get NameOwnerChanged arguments: %s: %s\n", + err.name, err.message); + dbus_error_free(&err); + return; + } + + if (strncmp(name, "org.mpris.", 10) != 0) + return; + + printf("NameOwnerChanged from=[%s] to=[%s]\n", from, to); + + tmp = eina_stringshare_add(name); + + if (to[0] == '\0') + { + players = eina_list_remove(players, tmp); + + /* vanished player was current? */ + if (tmp == bus_name) + { + /* make another player current */ + if (eina_list_count(players) > 0) + { + bus_name = players->data; + printf("use::%s", bus_name); + active = EINA_TRUE; + } + else + { + active = EINA_FALSE; + } + } + + eina_stringshare_del(tmp); + } + else + { + /* new player appeared? */ + if (!eina_list_data_find(players, tmp)) + { + eina_stringshare_ref(tmp); + players = eina_list_append(players, tmp); + } + + /* no active player - make player current */ + if (!active) + { + bus_name = tmp; + active = EINA_TRUE; + } + } + + eina_stringshare_del(tmp); +} + +static void +_dbus_cb_list_names(void *data, DBusMessage *msg, DBusError *err) +{ + DBusMessageIter array, iter, item, iter_val; + char *name; + + if (!_dbus_check_msg(msg, err)) return; + + dbus_message_iter_init(msg, &array); + if(dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_ARRAY) + { + dbus_message_iter_recurse(&array, &item); + + while(dbus_message_iter_get_arg_type(&item) == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic(&item, &name); + if (strncmp(name, "org.mpris.", 10) == 0) + { + printf("found %s", name); + + players = eina_list_append(players, eina_stringshare_add(name)); + } + + dbus_message_iter_next(&item); + } + } + + if (eina_list_count(players) > 0) + { + bus_name = players->data; + printf("use::%s", bus_name); + active = EINA_TRUE; + + + } +} + + +/* taken from curl: + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et + * al. + * + * Unescapes the given URL escaped string of given length. Returns a + * pointer to a malloced string with length given in *olen. + * If length == 0, the length is assumed to be strlen(string). + * If olen == NULL, no output length is stored. + */ +#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x))) + +static char * +_util_unescape(const char *string, int length) +{ + int alloc = (length?length:(int)strlen(string))+1; + char *ns = malloc(alloc); + unsigned char in; + int strindex=0; + unsigned long hex; + + if( !ns ) + return NULL; + + while(--alloc > 0) { + in = *string; + if(('%' == in) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { + /* this is two hexadecimal digits following a '%' */ + char hexstr[3]; + char *ptr; + hexstr[0] = string[1]; + hexstr[1] = string[2]; + hexstr[2] = 0; + + hex = strtoul(hexstr, &ptr, 16); + in = (unsigned char)(hex & (unsigned long) 0xFF); + // in = ultouc(hex); /* this long is never bigger than 255 anyway */ + + string+=2; + alloc-=2; + } + + ns[strindex++] = in; + string++; + } + ns[strindex]=0; /* terminate it */ + + return ns; +} + +#undef ISXDIGIT diff --git a/src/e_mod_main.h b/src/e_mod_main.h new file mode 100644 index 0000000..ea92bf8 --- /dev/null +++ b/src/e_mod_main.h @@ -0,0 +1,41 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#define D_(str) dgettext(PACKAGE, str) + +#ifndef E_MOD_MAIN_H +#define E_MOD_MAIN_H + +#define RESOLUTION_MINUTE 0 +#define RESOLUTION_SECOND 1 + +typedef struct _Config Config; +typedef struct _Config_Item Config_Item; + +struct _Config +{ + E_Module *module; + E_Config_Dialog *config_dialog; + E_Menu *menu; + Eina_List *instances; + Eina_List *items; +}; + +struct _Config_Item +{ + const char *id; + const char *player; + int show_popup; +}; + +EAPI extern E_Module_Api e_modapi; + +EAPI void *e_modapi_init (E_Module * m); +EAPI int e_modapi_shutdown (E_Module * m); +EAPI int e_modapi_save (E_Module * m); + +void _config_empris_module (Config_Item * ci); +void _empris_config_updated (Config_Item * ci); +extern Config *empris_config; + +#endif