forked from enlightenment/enlightenment
add teamwork module
see http://e18releasemanager.wordpress.com/2013/06/14/why/ for more info
This commit is contained in:
parent
c00785634a
commit
f4a327a0ca
|
@ -1,3 +1,7 @@
|
|||
2013-06-14 Mike Blumenkrantz
|
||||
|
||||
* add teamwork module
|
||||
|
||||
2013-06-13 Mike Blumenkrantz
|
||||
|
||||
* filemanager dnd operations now show all files when dragging
|
||||
|
|
374
INSTALL
374
INSTALL
|
@ -1,14 +1,370 @@
|
|||
COMPILING and INSTALLING:
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
If you got a official release tar archive do:
|
||||
./configure
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
( otherwise if you got this from enlightenment cvs do: ./autogen.sh )
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. This file is offered as-is,
|
||||
without warranty of any kind.
|
||||
|
||||
Then to compile:
|
||||
make
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
To install (run this as root, or the user who handles installs):
|
||||
make install
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package. Some packages provide this
|
||||
`INSTALL' file but do not implement all of the features documented
|
||||
below. The lack of an optional feature in a given package is not
|
||||
necessarily a bug. More recommendations for GNU packages can be found
|
||||
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||
|
||||
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 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.
|
||||
|
||||
Running `configure' might take a while. 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, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the `make install' phase executed with root
|
||||
privileges.
|
||||
|
||||
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior `make install' required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
6. 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.
|
||||
|
||||
7. Often, you can also type `make uninstall' to remove the installed
|
||||
files again. In practice, not all packages have tested that
|
||||
uninstallation works correctly, even though it is required by the
|
||||
GNU Coding Standards.
|
||||
|
||||
8. Some packages, particularly those that use Automake, provide `make
|
||||
distcheck', which can by used by developers to test that all other
|
||||
targets like `make install' and `make uninstall' work correctly.
|
||||
This target is generally not run by end users.
|
||||
|
||||
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=c99 CFLAGS=-g 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 can use 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 `..'. This
|
||||
is known as a "VPATH" build.
|
||||
|
||||
With a non-GNU `make', it is safer 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.
|
||||
|
||||
On MacOS X 10.5 and later systems, you can create libraries and
|
||||
executables that work on multiple system types--known as "fat" or
|
||||
"universal" binaries--by specifying multiple `-arch' options to the
|
||||
compiler but only a single `-arch' option to the preprocessor. Like
|
||||
this:
|
||||
|
||||
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CPP="gcc -E" CXXCPP="g++ -E"
|
||||
|
||||
This is not guaranteed to produce working output in all cases, you
|
||||
may have to build one architecture at a time and combine the results
|
||||
using the `lipo' tool if you have problems.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' 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. In general, the
|
||||
default for these options is expressed in terms of `${prefix}', so that
|
||||
specifying just `--prefix' will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to `configure'; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
`make install' command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, `make install
|
||||
prefix=/alternate/directory' will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
`${prefix}'. Any directories that were specified during `configure',
|
||||
but not in terms of `${prefix}', must each be overridden at install
|
||||
time for the entire installation to be relocated. The approach of
|
||||
makefile variable overrides for each directory variable is required by
|
||||
the GNU Coding Standards, and ideally causes no recompilation.
|
||||
However, some platforms have known limitations with the semantics of
|
||||
shared libraries that end up requiring recompilation when using this
|
||||
method, particularly noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the `DESTDIR' variable. For
|
||||
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||
`/alternate/directory' before all installation names. The approach of
|
||||
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of `${prefix}'
|
||||
at `configure' time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
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'.
|
||||
|
||||
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.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of `make' will be. For these packages, running `./configure
|
||||
--enable-silent-rules' sets the default to minimal output, which can be
|
||||
overridden with `make V=1'; while running `./configure
|
||||
--disable-silent-rules' sets the default to verbose, which can be
|
||||
overridden with `make V=0'.
|
||||
|
||||
Particular systems
|
||||
==================
|
||||
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||
CC is not installed, it is recommended to use the following options in
|
||||
order to use an ANSI C compiler:
|
||||
|
||||
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX `make' updates targets which have the same time stamps as
|
||||
their prerequisites, which makes it generally unusable when shipped
|
||||
generated files such as `configure' are involved. Use GNU `make'
|
||||
instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||
to try
|
||||
|
||||
./configure CC="cc"
|
||||
|
||||
and if that doesn't work, try
|
||||
|
||||
./configure CC="cc -nodtk"
|
||||
|
||||
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||
directory contains several dysfunctional programs; working variants of
|
||||
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||
in your `PATH', put it _after_ `/usr/bin'.
|
||||
|
||||
On Haiku, software installed for all users goes in `/boot/common',
|
||||
not `/usr/local'. It is recommended to use the following options:
|
||||
|
||||
./configure --prefix=/boot/common
|
||||
|
||||
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 option `--target=TYPE' 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
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of all of the options to `configure', and exit.
|
||||
|
||||
`--help=short'
|
||||
`--help=recursive'
|
||||
Print a summary of the options unique to this package's
|
||||
`configure', and exit. The `short' variant lists options used
|
||||
only in the top level, while the `recursive' variant lists options
|
||||
also present in any nested packages.
|
||||
|
||||
`--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.
|
||||
|
||||
`--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names::
|
||||
for more details, including other options available for fine-tuning
|
||||
the installation locations.
|
||||
|
||||
`--no-create'
|
||||
`-n'
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
NOTE: You MUST make install Enlightenment for it to run properly.
|
||||
|
|
1
NEWS
1
NEWS
|
@ -9,6 +9,7 @@ Additions:
|
|||
* bluez4: control bluetoothd daemon
|
||||
* conf_comp: configuration dialogs for composite, like in previous comp
|
||||
module
|
||||
* teamwork
|
||||
API:
|
||||
* Added action to reset filemanager
|
||||
* Added function to hide all active menus
|
||||
|
|
|
@ -903,6 +903,7 @@ AC_E_OPTIONAL_MODULE([systray], true)
|
|||
AC_E_OPTIONAL_MODULE([appmenu], true)
|
||||
AC_E_OPTIONAL_MODULE([physics], true, [CHECK_MODULE_PHYSICS])
|
||||
AC_E_OPTIONAL_MODULE([quickaccess], true)
|
||||
AC_E_OPTIONAL_MODULE([teamwork], true)
|
||||
AC_E_OPTIONAL_MODULE([shot], true)
|
||||
AC_E_OPTIONAL_MODULE([backlight], true)
|
||||
AC_E_OPTIONAL_MODULE([tasks], true)
|
||||
|
@ -1026,6 +1027,7 @@ src/modules/appmenu/module.desktop
|
|||
src/modules/conf_comp/module.desktop
|
||||
src/modules/physics/module.desktop
|
||||
src/modules/quickaccess/module.desktop
|
||||
src/modules/teamwork/module.desktop
|
||||
src/modules/shot/module.desktop
|
||||
src/modules/backlight/module.desktop
|
||||
src/modules/tasks/module.desktop
|
||||
|
|
|
@ -889,6 +889,7 @@ _e_module_whitelist_check(void)
|
|||
"syscon",
|
||||
"systray",
|
||||
"tasks",
|
||||
"teamwork",
|
||||
"temperature",
|
||||
"tiling",
|
||||
"winlist",
|
||||
|
|
|
@ -207,6 +207,10 @@ if USE_MODULE_QUICKACCESS
|
|||
include Makefile_quickaccess.am
|
||||
endif
|
||||
|
||||
if USE_MODULE_TEAMWORK
|
||||
include Makefile_teamwork.am
|
||||
endif
|
||||
|
||||
if USE_MODULE_SHOT
|
||||
include Makefile_shot.am
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
teamworkdir = $(MDIR)/teamwork
|
||||
teamwork_DATA = teamwork/e-module-teamwork.edj \
|
||||
teamwork/module.desktop
|
||||
|
||||
EXTRA_DIST += $(teamwork_DATA)
|
||||
|
||||
teamworkpkgdir = $(MDIR)/teamwork/$(MODULE_ARCH)
|
||||
teamworkpkg_LTLIBRARIES = teamwork/module.la
|
||||
|
||||
teamwork_module_la_SOURCES = teamwork/e_mod_main.c \
|
||||
teamwork/e_mod_config.c \
|
||||
teamwork/e_mod_main.h \
|
||||
teamwork/e_mod_tw.c \
|
||||
teamwork/sha1.c \
|
||||
teamwork/sha1.h
|
||||
|
||||
.PHONY: teamwork install-teamwork
|
||||
teamwork: $(teamworkpkg_LTLIBRARIES) $(teamwork_DATA)
|
||||
install-teamwork: install-teamworkDATA install-teamworkpkgLTLIBRARIES
|
Binary file not shown.
|
@ -0,0 +1,157 @@
|
|||
#include "e_mod_main.h"
|
||||
|
||||
struct _E_Config_Dialog_Data
|
||||
{
|
||||
int disable_media_fetch;
|
||||
double allowed_media_size;
|
||||
double allowed_media_age;
|
||||
|
||||
double mouse_out_delay;
|
||||
double popup_size;
|
||||
double popup_opacity;
|
||||
};
|
||||
|
||||
static void *
|
||||
_create_data(E_Config_Dialog *cfd EINA_UNUSED)
|
||||
{
|
||||
E_Config_Dialog_Data *cfdata;
|
||||
|
||||
cfdata = E_NEW(E_Config_Dialog_Data, 1);
|
||||
#define SET(X) \
|
||||
cfdata->X = tw_config->X
|
||||
SET(disable_media_fetch);
|
||||
SET(allowed_media_size);
|
||||
SET(allowed_media_age);
|
||||
|
||||
SET(mouse_out_delay);
|
||||
SET(popup_size);
|
||||
SET(popup_opacity);
|
||||
#undef SET
|
||||
return cfdata;
|
||||
}
|
||||
|
||||
static void
|
||||
_free_data(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
|
||||
{
|
||||
tw_mod->cfd = NULL;
|
||||
free(cfdata);
|
||||
}
|
||||
|
||||
static int
|
||||
_basic_check_changed(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
|
||||
{
|
||||
#define CHECK(X) \
|
||||
if (cfdata->X != tw_config->X) return 1
|
||||
|
||||
CHECK(disable_media_fetch);
|
||||
if (lround(cfdata->allowed_media_age) != tw_config->allowed_media_age) return 1;
|
||||
if (lround(cfdata->allowed_media_size) != tw_config->allowed_media_size) return 1;
|
||||
|
||||
if (fabs(cfdata->mouse_out_delay - tw_config->allowed_media_size) > 0.45) return 1;
|
||||
|
||||
if (fabs(cfdata->popup_size - tw_config->popup_size) > 0.9) return 1;
|
||||
if (fabs(cfdata->popup_opacity - tw_config->popup_opacity) > 0.9) return 1;
|
||||
|
||||
#undef CHECK
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Evas_Object *
|
||||
_basic_create_widgets(E_Config_Dialog *cfd EINA_UNUSED,
|
||||
Evas *evas,
|
||||
E_Config_Dialog_Data *cfdata)
|
||||
{
|
||||
Evas_Object *ob, *ol, *otb, *tab;
|
||||
|
||||
tab = e_widget_table_add(evas, 0);
|
||||
|
||||
otb = e_widget_toolbook_add(evas, 48 * e_scale, 48 * e_scale);
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
ol = e_widget_list_add(evas, 0, 0);
|
||||
|
||||
ob = e_widget_check_add(evas, _("Disable remote media fetching"), &cfdata->disable_media_fetch);
|
||||
e_widget_list_object_append(ol, ob, 1, 0, 0.5);
|
||||
|
||||
ob = e_widget_label_add(evas, _("Maximum media cache size in RAM"));
|
||||
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
|
||||
ob = e_widget_slider_add(evas, 1, 0, _("%4.0f MiB"), 0, 1024, 16, 0, &cfdata->allowed_media_size, NULL, 150);
|
||||
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
|
||||
ob = e_widget_label_add(evas, _("Maximum media cache age on disk"));
|
||||
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
|
||||
ob = e_widget_slider_add(evas, 1, 0, _("%3.0f Days"), -1, 180, 1, 0, &cfdata->allowed_media_age, NULL, 150);
|
||||
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
|
||||
|
||||
e_widget_toolbook_page_append(otb, NULL, _("Cache"), ol, 1, 1, 1, 1, 0.5, 0.5);
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
ol = e_widget_list_add(evas, 0, 0);
|
||||
|
||||
ob = e_widget_label_add(evas, _("Mouse-out hide delay"));
|
||||
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
|
||||
ob = e_widget_slider_add(evas, 1, 0, _("%1.1f seconds"), 0, 5, 0.5, 0, &cfdata->mouse_out_delay, NULL, 150);
|
||||
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
|
||||
ob = e_widget_label_add(evas, _("Maximum size (Percentage of screens size)"));
|
||||
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
|
||||
ob = e_widget_slider_add(evas, 1, 0, _("%3.0f"), 10, 100, 1, 0, &cfdata->popup_size, NULL, 150);
|
||||
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
|
||||
ob = e_widget_label_add(evas, _("Opacity"));
|
||||
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
|
||||
ob = e_widget_slider_add(evas, 1, 0, _("%3.0f"), 10, 100, 1, 0, &cfdata->popup_opacity, NULL, 150);
|
||||
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
|
||||
|
||||
e_widget_toolbook_page_append(otb, NULL, _("Popups"), ol, 1, 1, 1, 1, 0.5, 0.5);
|
||||
|
||||
e_widget_toolbook_page_show(otb, 0);
|
||||
|
||||
e_widget_table_object_append(tab, otb, 0, 0, 1, 1, 1, 1, 1, 1);
|
||||
return tab;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_basic_apply_data(E_Config_Dialog *cfd EINA_UNUSED,
|
||||
E_Config_Dialog_Data *cfdata)
|
||||
{
|
||||
|
||||
#define SET(X) tw_config->X = cfdata->X
|
||||
SET(disable_media_fetch);
|
||||
SET(allowed_media_size);
|
||||
SET(allowed_media_age);
|
||||
|
||||
SET(mouse_out_delay);
|
||||
SET(popup_size);
|
||||
if (fabs(cfdata->popup_opacity - tw_config->popup_opacity) > 0.9)
|
||||
{
|
||||
SET(popup_opacity);
|
||||
tw_popup_opacity_set();
|
||||
}
|
||||
|
||||
e_config_save_queue();
|
||||
return 1;
|
||||
}
|
||||
|
||||
EINTERN E_Config_Dialog *
|
||||
e_int_config_teamwork_module(E_Container *con, const char *params EINA_UNUSED)
|
||||
{
|
||||
E_Config_Dialog *cfd;
|
||||
E_Config_Dialog_View *v;
|
||||
char buf[4096];
|
||||
|
||||
if (tw_mod->cfd) return NULL;
|
||||
snprintf(buf, sizeof(buf), "%s/e-module-teamwork.edj", e_module_dir_get(tw_mod->module));
|
||||
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;
|
||||
v->basic.check_changed = _basic_check_changed;
|
||||
|
||||
cfd = e_config_dialog_new(con, _("Teamwork Settings"),
|
||||
"E", "applications/teamwork", buf, 32, v, tw_mod);
|
||||
tw_mod->cfd = cfd;
|
||||
return cfd;
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
#include "e_mod_main.h"
|
||||
#include "sha1.h"
|
||||
|
||||
EINTERN int _e_teamwork_log_dom = -1;
|
||||
EINTERN Mod *tw_mod = NULL;
|
||||
EINTERN Teamwork_Config *tw_config = NULL;
|
||||
|
||||
EAPI E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Teamwork"};
|
||||
|
||||
static E_Config_DD *conf_edd = NULL;
|
||||
|
||||
static E_Action *e_tw_toggle = NULL;
|
||||
static const char _act_toggle[] = "tw_toggle";
|
||||
static const char _e_tw_name[] = N_("Teamwork");
|
||||
static const char _lbl_toggle[] = N_("Toggle Popup Visibility");
|
||||
|
||||
static const char *
|
||||
_sha1_to_string(const unsigned char *hashout)
|
||||
{
|
||||
const char hextab[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
char sha1[41] = {0};
|
||||
unsigned int i = 0;
|
||||
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
sha1[2 * i] = hextab[(hashout[i] >> 4) & 0x0f];
|
||||
sha1[2 * i + 1] = hextab[hashout[i] & 0x0f];
|
||||
}
|
||||
return eina_stringshare_add(sha1);
|
||||
}
|
||||
|
||||
const char *
|
||||
sha1_encode(const unsigned char *data, size_t len)
|
||||
{
|
||||
SHA_CTX2 ctx;
|
||||
unsigned char hashout[20];
|
||||
unsigned char *buf;
|
||||
|
||||
if (EINA_UNLIKELY(len > 65000))
|
||||
buf = malloc(len);
|
||||
else
|
||||
buf = alloca(len);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(buf, NULL);
|
||||
memcpy(buf, data, len);
|
||||
|
||||
SHA1_Init2(&ctx);
|
||||
SHA1_Update2(&ctx, buf, len);
|
||||
SHA1_Final2(hashout, &ctx);
|
||||
if (EINA_UNLIKELY(len > 65000)) free(buf);
|
||||
return _sha1_to_string(hashout);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
static Teamwork_Config *
|
||||
e_tw_config_new(void)
|
||||
{
|
||||
Teamwork_Config *cf;
|
||||
|
||||
cf = E_NEW(Teamwork_Config, 1);
|
||||
cf->config_version = MOD_CONFIG_FILE_VERSION;
|
||||
|
||||
cf->allowed_media_size = 10; // 10 megabytes
|
||||
cf->allowed_media_age = 3; // 3 days
|
||||
|
||||
cf->mouse_out_delay = 0.0;
|
||||
cf->popup_size = 10.0;
|
||||
cf->popup_opacity = 90.0;
|
||||
|
||||
return cf;
|
||||
}
|
||||
|
||||
static E_Config_DD *
|
||||
e_tw_config_dd_new(void)
|
||||
{
|
||||
conf_edd = E_CONFIG_DD_NEW("Teamwork_Config", Teamwork_Config);
|
||||
|
||||
#undef T
|
||||
#undef D
|
||||
#define T Teamwork_Config
|
||||
#define D conf_edd
|
||||
E_CONFIG_VAL(D, T, config_version, UINT);
|
||||
E_CONFIG_VAL(D, T, disable_media_fetch, UCHAR);
|
||||
E_CONFIG_VAL(D, T, allowed_media_size, LL);
|
||||
E_CONFIG_VAL(D, T, allowed_media_age, INT);
|
||||
|
||||
E_CONFIG_VAL(D, T, mouse_out_delay, DOUBLE);
|
||||
E_CONFIG_VAL(D, T, popup_size, DOUBLE);
|
||||
E_CONFIG_VAL(D, T, popup_opacity, DOUBLE);
|
||||
return conf_edd;
|
||||
}
|
||||
//////////////////////////////
|
||||
static void
|
||||
e_tw_act_toggle_cb(E_Object *obj EINA_UNUSED, const char *params EINA_UNUSED)
|
||||
{
|
||||
if (!tw_mod->pop) return;
|
||||
if (tw_mod->sticky)
|
||||
tw_hide(NULL);
|
||||
tw_mod->sticky = !tw_mod->sticky;
|
||||
}
|
||||
//////////////////////////////
|
||||
EAPI void *
|
||||
e_modapi_init(E_Module *m)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
E_Configure_Option *co;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s/e-module-teamwork.edj", e_module_dir_get(m));
|
||||
e_configure_registry_category_add("applications", 20, _("Apps"), NULL,
|
||||
"preferences-applications");
|
||||
e_configure_registry_item_add("applications/teamwork", 1, _("Teamwork"), NULL,
|
||||
buf, e_int_config_teamwork_module);
|
||||
|
||||
tw_mod = E_NEW(Mod, 1);
|
||||
tw_mod->module = m;
|
||||
m->data = tw_mod;
|
||||
conf_edd = e_tw_config_dd_new();
|
||||
tw_config = e_config_domain_load("module.teamwork", conf_edd);
|
||||
if (tw_config)
|
||||
{
|
||||
if (!e_util_module_config_check(_("Teamwork"), tw_config->config_version, MOD_CONFIG_FILE_VERSION))
|
||||
E_FREE_FUNC(tw_config, free);
|
||||
}
|
||||
|
||||
if (tw_config)
|
||||
{
|
||||
/* sanity checks */
|
||||
tw_config->mouse_out_delay = E_CLAMP(tw_config->mouse_out_delay, 0.0, 5.0);
|
||||
tw_config->popup_size = E_CLAMP(tw_config->popup_size, 10.0, 100.0);
|
||||
tw_config->popup_opacity = E_CLAMP(tw_config->popup_opacity, 10.0, 100.0);
|
||||
}
|
||||
else
|
||||
tw_config = e_tw_config_new();
|
||||
tw_config->config_version = MOD_CONFIG_FILE_VERSION;
|
||||
|
||||
_e_teamwork_log_dom = eina_log_domain_register("teamwork", EINA_COLOR_ORANGE);
|
||||
eina_log_domain_level_set("teamwork", EINA_LOG_LEVEL_DBG);
|
||||
|
||||
if (!e_tw_init())
|
||||
{
|
||||
e_modapi_shutdown(NULL);
|
||||
return NULL;
|
||||
}
|
||||
e_tw_toggle = e_action_add(_act_toggle);
|
||||
e_tw_toggle->func.go = e_tw_act_toggle_cb;
|
||||
e_action_predef_name_set(_e_tw_name, _lbl_toggle, _act_toggle, NULL, NULL, 0);
|
||||
|
||||
e_configure_option_domain_current_set("teamwork");
|
||||
|
||||
E_CONFIGURE_OPTION_ADD_CUSTOM(co, "teamwork-settings", _("Teamwork settings panel"), _("teamwork"), _("applications"));
|
||||
co->info = eina_stringshare_add("applications/teamwork");
|
||||
E_CONFIGURE_OPTION_ICON(co, buf);
|
||||
E_CONFIGURE_OPTION_ADD(co, BOOL, disable_media_fetch, tw_config, _("Disable Teamwork remote media fetching"), _("teamwork"));
|
||||
E_CONFIGURE_OPTION_ADD(co, DOUBLE, allowed_media_size, tw_config, _("Maximum total size of Teamwork media to keep in RAM"), _("teamwork"), _("cache"));
|
||||
E_CONFIGURE_OPTION_MINMAX_STEP_FMT(co, 0, 1024, 16, _("%4.0f MiB"));
|
||||
E_CONFIGURE_OPTION_HELP(co, _("This option determines how much memory will be used to cache recent media for faster loading."));
|
||||
E_CONFIGURE_OPTION_ADD(co, DOUBLE, allowed_media_age, tw_config, _("Maximum age for a disk-cached Teamwork media item"), _("teamwork"), _("cache"));
|
||||
E_CONFIGURE_OPTION_MINMAX_STEP_FMT(co, -1, 180, 1, _("%3.0f Days"));
|
||||
E_CONFIGURE_OPTION_HELP(co, _("This option determines how long media will remain in the disk cache before it is pruned.</ps>"
|
||||
"Set to -1 to never delete media, or to 0 to never cache media on disk."));
|
||||
|
||||
E_CONFIGURE_OPTION_ADD(co, DOUBLE, mouse_out_delay, tw_config, _("Delay before closing a Teamwork popup on mouse-out"), _("teamwork"), _("mouse"));
|
||||
E_CONFIGURE_OPTION_MINMAX_STEP_FMT(co, 0, 5, 0.5, _("%1.1f seconds"));
|
||||
E_CONFIGURE_OPTION_ADD(co, DOUBLE, popup_size, tw_config, _("Maximum percentage of screen to use for Teamwork popups"), _("teamwork"), _("screen"));
|
||||
E_CONFIGURE_OPTION_MINMAX_STEP_FMT(co, 10, 100, 1, _("%3.0f"));
|
||||
E_CONFIGURE_OPTION_ADD(co, DOUBLE, popup_opacity, tw_config, _("Opacity to use for Teamwork popups"), _("teamwork"));
|
||||
E_CONFIGURE_OPTION_MINMAX_STEP_FMT(co, 10, 100, 1, _("%3.0f"));
|
||||
co->funcs[0].none = tw_popup_opacity_set;
|
||||
|
||||
e_configure_option_category_tag_add(_("applications"), _("teamwork"));
|
||||
e_configure_option_category_tag_add(_("teamwork"), _("teamwork"));
|
||||
e_configure_option_category_icon_set(_("teamwork"), buf);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
e_modapi_shutdown(E_Module *m __UNUSED__)
|
||||
{
|
||||
e_tw_shutdown();
|
||||
|
||||
E_CONFIG_DD_FREE(conf_edd);
|
||||
eina_log_domain_unregister(_e_teamwork_log_dom);
|
||||
_e_teamwork_log_dom = -1;
|
||||
|
||||
e_configure_registry_item_del("applications/teamwork");
|
||||
e_configure_registry_category_del("applications");
|
||||
|
||||
e_configure_option_domain_clear("teamwork");
|
||||
e_configure_option_category_tag_del(_("teamwork"), _("teamwork"));
|
||||
e_configure_option_category_tag_del(_("applications"), _("teamwork"));
|
||||
|
||||
e_action_predef_name_del(_e_tw_name, _lbl_toggle);
|
||||
e_action_del(_act_toggle);
|
||||
e_tw_toggle = NULL;
|
||||
|
||||
E_FREE(tw_config);
|
||||
E_FREE(tw_mod);
|
||||
return 1;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
e_modapi_save(E_Module *m __UNUSED__)
|
||||
{
|
||||
e_config_domain_save("module.teamwork", conf_edd, tw_config);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#ifndef E_MOD_MAIN_H
|
||||
#define E_MOD_MAIN_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "e.h"
|
||||
|
||||
/* Increment for Major Changes */
|
||||
#define MOD_CONFIG_FILE_EPOCH 1
|
||||
/* Increment for Minor Changes (ie: user doesn't need a new config) */
|
||||
#define MOD_CONFIG_FILE_GENERATION 0
|
||||
#define MOD_CONFIG_FILE_VERSION ((MOD_CONFIG_FILE_EPOCH * 1000000) + MOD_CONFIG_FILE_GENERATION)
|
||||
|
||||
typedef struct Teamwork_Config
|
||||
{
|
||||
unsigned int config_version;
|
||||
|
||||
Eina_Bool disable_media_fetch;
|
||||
long long int allowed_media_size;
|
||||
int allowed_media_age;
|
||||
|
||||
double mouse_out_delay;
|
||||
double popup_size;
|
||||
double popup_opacity;
|
||||
} Teamwork_Config;
|
||||
|
||||
typedef struct Mod
|
||||
{
|
||||
E_Module *module;
|
||||
E_Config_Dialog *cfd;
|
||||
size_t media_size;
|
||||
Eina_Inlist *media_list;
|
||||
Eina_Hash *media;
|
||||
E_Popup *pop;
|
||||
Eina_Bool sticky : 1;
|
||||
} Mod;
|
||||
|
||||
extern Teamwork_Config *tw_config;
|
||||
extern Mod *tw_mod;
|
||||
extern int _e_teamwork_log_dom;
|
||||
|
||||
EINTERN const char *sha1_encode(const unsigned char *data, size_t len);
|
||||
|
||||
EINTERN int e_tw_init(void);
|
||||
EINTERN void e_tw_shutdown(void);
|
||||
EINTERN Eina_Bool tw_hide(void *d EINA_UNUSED);
|
||||
EINTERN void tw_popup_opacity_set(void);
|
||||
|
||||
EINTERN E_Config_Dialog *e_int_config_teamwork_module(E_Container *con, const char *params EINA_UNUSED);
|
||||
|
||||
EAPI int e_modapi_shutdown(E_Module *m __UNUSED__);
|
||||
#undef DBG
|
||||
#undef INF
|
||||
#undef WRN
|
||||
#undef ERR
|
||||
#undef CRIT
|
||||
#define DBG(...) EINA_LOG_DOM_DBG(_e_teamwork_log_dom, __VA_ARGS__)
|
||||
#define INF(...) EINA_LOG_DOM_INFO(_e_teamwork_log_dom, __VA_ARGS__)
|
||||
#define WRN(...) EINA_LOG_DOM_WARN(_e_teamwork_log_dom, __VA_ARGS__)
|
||||
#define ERR(...) EINA_LOG_DOM_ERR(_e_teamwork_log_dom, __VA_ARGS__)
|
||||
#define CRIT(...) EINA_LOG_DOM_CRIT(_e_teamwork_log_dom, __VA_ARGS__)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,873 @@
|
|||
#include "e_mod_main.h"
|
||||
|
||||
#define IMAGE_FETCH_TRIES 5
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *sha1;
|
||||
unsigned long long timestamp;
|
||||
} Media_Cache;
|
||||
|
||||
typedef struct Media_Cache_List
|
||||
{
|
||||
Eina_List *cache;
|
||||
} Media_Cache_List;
|
||||
|
||||
typedef struct Media
|
||||
{
|
||||
EINA_INLIST;
|
||||
Ecore_Con_Url *client;
|
||||
Eina_Binbuf *buf;
|
||||
const char *addr;
|
||||
unsigned long long timestamp;
|
||||
unsigned int tries;
|
||||
Eina_Bool dummy : 1;
|
||||
Eina_Bool valid : 1;
|
||||
Eina_Bool show : 1;
|
||||
} Media;
|
||||
|
||||
static Eet_File *media = NULL;
|
||||
static Eet_File *dummies = NULL;
|
||||
static Eet_Data_Descriptor *cleaner_edd = NULL;
|
||||
static Eet_Data_Descriptor *cache_edd = NULL;
|
||||
static Ecore_Idler *media_cleaner = NULL;
|
||||
static Eina_List *handlers = NULL;
|
||||
static Media_Cache_List *tw_cache_list = NULL;
|
||||
|
||||
static Evas_Point last_coords = {0};
|
||||
|
||||
static Ecore_Timer *tw_hide_timer = NULL;
|
||||
|
||||
static Eldbus_Service_Interface *tw_dbus_iface = NULL;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TEAMWORK_LINK_TYPE_NONE,
|
||||
TEAMWORK_LINK_TYPE_LOCAL_FILE,
|
||||
TEAMWORK_LINK_TYPE_LOCAL_DIRECTORY,
|
||||
TEAMWORK_LINK_TYPE_REMOTE
|
||||
} Teamwork_Link_Type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TEAMWORK_SIGNAL_LINK_DOWNLOADING,
|
||||
TEAMWORK_SIGNAL_LINK_PROGRESS,
|
||||
TEAMWORK_SIGNAL_LINK_COMPLETE,
|
||||
TEAMWORK_SIGNAL_LINK_INVALID,
|
||||
} Teamwork_Signal;
|
||||
|
||||
static const Eldbus_Signal tw_signals[] =
|
||||
{
|
||||
[TEAMWORK_SIGNAL_LINK_DOWNLOADING] = {"LinkDownloading", ELDBUS_ARGS({"s", "URI"}, {"u", "Timestamp"}), 0},
|
||||
[TEAMWORK_SIGNAL_LINK_PROGRESS] = {"LinkProgress", ELDBUS_ARGS({"s", "URI"}, {"u", "Timestamp"}, {"d", "Percent Completion"}), 0},
|
||||
[TEAMWORK_SIGNAL_LINK_COMPLETE] = {"LinkComplete", ELDBUS_ARGS({"s", "URI"}, {"u", "Timestamp"}), 0},
|
||||
[TEAMWORK_SIGNAL_LINK_INVALID] = {"LinkInvalid", ELDBUS_ARGS({"s", "URI"}, {"u", "Timestamp"}), 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static void tw_show(Media *i);
|
||||
static void tw_show_local_file(const char *uri);
|
||||
static void tw_show_local_dir(const char *uri);
|
||||
static int tw_media_add(const char *url, Eina_Binbuf *buf, unsigned long long timestamp);
|
||||
static void download_media_cleanup(void);
|
||||
static void tw_dummy_add(const char *url);
|
||||
static Eina_Bool tw_dummy_check(const char *url);
|
||||
static void tw_media_ping(const char *url, unsigned long long timestamp);
|
||||
static Eina_Binbuf *tw_media_get(const char *url, unsigned long long timestamp);
|
||||
static Eina_Bool tw_idler_start(void);
|
||||
|
||||
static void
|
||||
dbus_signal_link_complete(Media *i)
|
||||
{
|
||||
unsigned int u = ecore_time_unix_get();
|
||||
if (i->show) tw_show(i);
|
||||
i->show = 0;
|
||||
eldbus_service_signal_emit(tw_dbus_iface, TEAMWORK_SIGNAL_LINK_COMPLETE, i->addr, u);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_signal_link_invalid(Media *i)
|
||||
{
|
||||
unsigned int u = ecore_time_unix_get();
|
||||
eldbus_service_signal_emit(tw_dbus_iface, TEAMWORK_SIGNAL_LINK_INVALID, i->addr, u);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_signal_link_progress(Media *i, double pr)
|
||||
{
|
||||
unsigned int u = ecore_time_unix_get();
|
||||
eldbus_service_signal_emit(tw_dbus_iface, TEAMWORK_SIGNAL_LINK_PROGRESS, i->addr, u, pr);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_signal_link_downloading(Media *i)
|
||||
{
|
||||
unsigned int u = ecore_time_unix_get();
|
||||
eldbus_service_signal_emit(tw_dbus_iface, TEAMWORK_SIGNAL_LINK_DOWNLOADING, i->addr, u);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
download_media_complete(void *data, int type EINA_UNUSED, Ecore_Con_Event_Url_Complete *ev)
|
||||
{
|
||||
Media *i;
|
||||
|
||||
if (data != tw_mod) return ECORE_CALLBACK_RENEW;
|
||||
i = ecore_con_url_data_get(ev->url_con);
|
||||
if (!i) return ECORE_CALLBACK_RENEW;
|
||||
if (!i->valid) return ECORE_CALLBACK_RENEW;
|
||||
i->timestamp = (unsigned long long)ecore_time_unix_get();
|
||||
if (tw_media_add(i->addr, i->buf, i->timestamp) == 1)
|
||||
tw_mod->media_size += eina_binbuf_length_get(i->buf);
|
||||
E_FREE_FUNC(i->client, ecore_con_url_free);
|
||||
dbus_signal_link_complete(i);
|
||||
download_media_cleanup();
|
||||
INF("MEDIA CACHE: %zu bytes", tw_mod->media_size);
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
download_media_data(void *data, int type EINA_UNUSED, Ecore_Con_Event_Url_Data *ev)
|
||||
{
|
||||
Media *i;
|
||||
|
||||
if (data != tw_mod) return ECORE_CALLBACK_RENEW;
|
||||
i = ecore_con_url_data_get(ev->url_con);
|
||||
if (!i) return ECORE_CALLBACK_RENEW;
|
||||
if (i->dummy) return ECORE_CALLBACK_RENEW;
|
||||
if (!i->buf) i->buf = eina_binbuf_new();
|
||||
eina_binbuf_append_length(i->buf, ev->data, ev->size);
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
download_media_status(void *data, int type EINA_UNUSED, Ecore_Con_Event_Url_Progress *ev)
|
||||
{
|
||||
int status;
|
||||
const char *h;
|
||||
Media *i;
|
||||
const Eina_List *l;
|
||||
|
||||
if (data != tw_mod) return ECORE_CALLBACK_RENEW;
|
||||
i = ecore_con_url_data_get(ev->url_con);
|
||||
if (!i) return ECORE_CALLBACK_RENEW;
|
||||
|
||||
if (i->valid) return ECORE_CALLBACK_RENEW; //already checked
|
||||
status = ecore_con_url_status_code_get(ev->url_con);
|
||||
if (!status) return ECORE_CALLBACK_RENEW; //not ready yet
|
||||
DBG("%i code for media: %s", status, i->addr);
|
||||
if (status != 200)
|
||||
{
|
||||
E_FREE_FUNC(i->buf, eina_binbuf_free);
|
||||
E_FREE_FUNC(i->client, ecore_con_url_free);
|
||||
if ((status >= 400) || (status <= 300)) goto dummy;
|
||||
if (++i->tries < IMAGE_FETCH_TRIES)
|
||||
{
|
||||
i->client = ecore_con_url_new(i->addr);
|
||||
ecore_con_url_data_set(i->client, i);
|
||||
if (!ecore_con_url_get(i->client)) goto dummy;
|
||||
}
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
EINA_LIST_FOREACH(ecore_con_url_response_headers_get(ev->url_con), l, h)
|
||||
{
|
||||
if (strncasecmp(h, "Content-Type: ", sizeof("Content-Type: ") - 1)) continue;
|
||||
if (strncasecmp(h + sizeof("Content-Type: ") - 1, "image/", 6)) goto dummy;
|
||||
}
|
||||
i->valid = !i->dummy;
|
||||
if (i->valid) dbus_signal_link_progress(i, ev->down.now / ev->down.total);
|
||||
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
dummy:
|
||||
dbus_signal_link_invalid(i);
|
||||
tw_dummy_add(i->addr);
|
||||
i->dummy = EINA_TRUE;
|
||||
E_FREE_FUNC(i->buf, eina_binbuf_free);
|
||||
E_FREE_FUNC(i->client, ecore_con_url_free);
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
||||
static int
|
||||
download_media_sort_cb(Media *a, Media *b)
|
||||
{
|
||||
long long diff;
|
||||
diff = a->timestamp - b->timestamp;
|
||||
if (diff < 0) return -1;
|
||||
if (!diff) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Media *
|
||||
download_media_add(const char *url)
|
||||
{
|
||||
Media *i;
|
||||
unsigned long long t;
|
||||
|
||||
t = (unsigned long long)ecore_time_unix_get();
|
||||
|
||||
i = eina_hash_find(tw_mod->media, url);
|
||||
if (i)
|
||||
{
|
||||
if (i->buf)
|
||||
{
|
||||
i->timestamp = t;
|
||||
tw_media_ping(url, i->timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* randomly deleted during cache pruning */
|
||||
i->buf = tw_media_get(url, t);
|
||||
tw_mod->media_size += eina_binbuf_length_get(i->buf);
|
||||
}
|
||||
tw_mod->media_list = eina_inlist_promote(tw_mod->media_list, EINA_INLIST_GET(i));
|
||||
download_media_cleanup();
|
||||
return i;
|
||||
}
|
||||
if (tw_dummy_check(url)) return NULL;
|
||||
if (tw_config->disable_media_fetch) return NULL;
|
||||
i = calloc(1, sizeof(Media));
|
||||
i->addr = eina_stringshare_add(url);
|
||||
i->buf = tw_media_get(url, t);
|
||||
if (i->buf)
|
||||
tw_mod->media_size += eina_binbuf_length_get(i->buf);
|
||||
else
|
||||
{
|
||||
i->client = ecore_con_url_new(url);
|
||||
ecore_con_url_data_set(i->client, i);
|
||||
ecore_con_url_get(i->client);
|
||||
dbus_signal_link_downloading(i);
|
||||
}
|
||||
eina_hash_direct_add(tw_mod->media, url, i);
|
||||
tw_mod->media_list = eina_inlist_sorted_insert(tw_mod->media_list, EINA_INLIST_GET(i), (Eina_Compare_Cb)download_media_sort_cb);
|
||||
return i;
|
||||
}
|
||||
|
||||
static void
|
||||
download_media_free(Media *i)
|
||||
{
|
||||
if (!i) return;
|
||||
tw_mod->media_list = eina_inlist_remove(tw_mod->media_list, EINA_INLIST_GET(i));
|
||||
if (i->client) ecore_con_url_free(i->client);
|
||||
if (i->buf) eina_binbuf_free(i->buf);
|
||||
eina_stringshare_del(i->addr);
|
||||
free(i);
|
||||
}
|
||||
|
||||
static void
|
||||
download_media_cleanup(void)
|
||||
{
|
||||
Media *i;
|
||||
Eina_Inlist *l;
|
||||
|
||||
if (tw_config->allowed_media_age)
|
||||
{
|
||||
if (tw_config->allowed_media_size < 0) return;
|
||||
if ((size_t)tw_config->allowed_media_size > (tw_mod->media_size / 1024 / 1024)) return;
|
||||
}
|
||||
if (!tw_mod->media_list) return;
|
||||
l = tw_mod->media_list->last;
|
||||
while (l)
|
||||
{
|
||||
i = EINA_INLIST_CONTAINER_GET(l, Media);
|
||||
l = l->prev;
|
||||
if (!i->buf) continue;
|
||||
/* only free the buffers here where possible to avoid having to deal with multiple list entries */
|
||||
if (tw_mod->media_size && (tw_mod->media_size >= eina_binbuf_length_get(i->buf)))
|
||||
tw_mod->media_size -= eina_binbuf_length_get(i->buf);
|
||||
E_FREE_FUNC(i->buf, eina_binbuf_free);
|
||||
if (!tw_config->allowed_media_age)
|
||||
/* if caching is disabled, just delete */
|
||||
eina_hash_del_by_key(tw_mod->media, i->addr);
|
||||
if ((size_t)tw_config->allowed_media_size > (tw_mod->media_size / 1024 / 1024))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static Teamwork_Link_Type
|
||||
dbus_link_uri_local_type_get(const char *uri)
|
||||
{
|
||||
size_t len = strlen(uri);
|
||||
|
||||
if (uri[len - 1] == '/') return TEAMWORK_LINK_TYPE_LOCAL_DIRECTORY;
|
||||
return TEAMWORK_LINK_TYPE_LOCAL_FILE;
|
||||
}
|
||||
|
||||
static Teamwork_Link_Type
|
||||
dbus_link_uri_type_get(const char *uri)
|
||||
{
|
||||
if (!uri[0]) return TEAMWORK_LINK_TYPE_NONE; //invalid
|
||||
if (uri[0] == '/') return dbus_link_uri_local_type_get(uri + 1); //probably a file?
|
||||
if ((!strncasecmp(uri, "http://", 7)) || (!strncasecmp(uri, "https://", 8))) return TEAMWORK_LINK_TYPE_REMOTE;
|
||||
if (!strncmp(uri, "file://", 7)) return dbus_link_uri_local_type_get(uri + 7);
|
||||
WRN("Unknown link type for '%s'", uri);
|
||||
return TEAMWORK_LINK_TYPE_NONE;
|
||||
}
|
||||
|
||||
static Eldbus_Message *
|
||||
dbus_link_detect_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
|
||||
{
|
||||
const char *uri;
|
||||
unsigned int t;
|
||||
|
||||
if (!tw_config->allowed_media_age) goto out;
|
||||
if (!eldbus_message_arguments_get(msg, "su", &uri, &t)) goto out;
|
||||
|
||||
if (dbus_link_uri_type_get(uri) == TEAMWORK_LINK_TYPE_REMOTE)
|
||||
download_media_add(uri);
|
||||
out:
|
||||
return eldbus_message_method_return_new(msg);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_link_show_helper(const char *uri, Eina_Bool signal_open)
|
||||
{
|
||||
Teamwork_Link_Type type;
|
||||
|
||||
if (tw_mod->pop && (!e_util_strcmp(e_object_data_get(E_OBJECT(tw_mod->pop)), uri))) return;
|
||||
type = dbus_link_uri_type_get(uri);
|
||||
switch (type)
|
||||
{
|
||||
case TEAMWORK_LINK_TYPE_NONE: break;
|
||||
case TEAMWORK_LINK_TYPE_LOCAL_DIRECTORY:
|
||||
if (signal_open) tw_show_local_dir(uri);
|
||||
break;
|
||||
case TEAMWORK_LINK_TYPE_LOCAL_FILE:
|
||||
tw_show_local_file(uri);
|
||||
break;
|
||||
case TEAMWORK_LINK_TYPE_REMOTE:
|
||||
{
|
||||
Media *i;
|
||||
|
||||
i = eina_hash_find(tw_mod->media, uri);
|
||||
if (!i)
|
||||
{
|
||||
if (tw_dummy_check(uri)) break;
|
||||
i = download_media_add(uri);
|
||||
if (i)
|
||||
{
|
||||
if (i->buf) tw_show(i);
|
||||
else if (i->dummy) break;
|
||||
else i->show = 1;
|
||||
}
|
||||
}
|
||||
else if (!i->dummy) tw_show(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Eldbus_Message *
|
||||
dbus_link_show_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
|
||||
{
|
||||
const char *uri;
|
||||
|
||||
if (eldbus_message_arguments_get(msg, "s", &uri))
|
||||
{
|
||||
last_coords.x = last_coords.y = -1;
|
||||
dbus_link_show_helper(uri, 1);
|
||||
}
|
||||
return eldbus_message_method_return_new(msg);
|
||||
}
|
||||
|
||||
static Eldbus_Message *
|
||||
dbus_link_hide_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
|
||||
{
|
||||
const char *uri;
|
||||
|
||||
if (eldbus_message_arguments_get(msg, "s", &uri))
|
||||
{
|
||||
if (tw_mod->pop && (!tw_mod->sticky) && (!e_util_strcmp(e_object_data_get(E_OBJECT(tw_mod->pop)), uri)))
|
||||
tw_hide(NULL);
|
||||
}
|
||||
return eldbus_message_method_return_new(msg);
|
||||
}
|
||||
|
||||
static Eldbus_Message *
|
||||
dbus_link_mouse_in_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
|
||||
{
|
||||
const char *uri;
|
||||
unsigned int t;
|
||||
|
||||
if (eldbus_message_arguments_get(msg, "suii", &uri, &t, &last_coords.x, &last_coords.y))
|
||||
dbus_link_show_helper(uri, 0);
|
||||
return eldbus_message_method_return_new(msg);
|
||||
}
|
||||
|
||||
static Eldbus_Message *
|
||||
dbus_link_mouse_out_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
|
||||
{
|
||||
const char *uri;
|
||||
unsigned int t;
|
||||
|
||||
if (eldbus_message_arguments_get(msg, "suii", &uri, &t, &last_coords.x, &last_coords.y))
|
||||
{
|
||||
if (tw_mod->pop && (!tw_mod->sticky) && (!e_util_strcmp(e_object_data_get(E_OBJECT(tw_mod->pop)), uri)))
|
||||
{
|
||||
if (tw_config->mouse_out_delay)
|
||||
{
|
||||
if (tw_hide_timer) ecore_timer_reset(tw_hide_timer);
|
||||
else tw_hide_timer = ecore_timer_add(tw_config->mouse_out_delay, tw_hide, NULL);
|
||||
}
|
||||
else
|
||||
tw_hide(NULL);
|
||||
}
|
||||
}
|
||||
return eldbus_message_method_return_new(msg);
|
||||
}
|
||||
|
||||
static Eldbus_Message *
|
||||
dbus_link_open_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
|
||||
{
|
||||
const char *uri;
|
||||
|
||||
if (eldbus_message_arguments_get(msg, "s", &uri))
|
||||
{
|
||||
char *sb;
|
||||
size_t size = 4096, len = sizeof(E_BINDIR "/enlightenment_open ") - 1;
|
||||
|
||||
sb = malloc(size);
|
||||
memcpy(sb, E_BINDIR "/enlightenment_open ", len);
|
||||
sb = e_util_string_append_quoted(sb, &size, &len, uri);
|
||||
ecore_exe_run(sb, NULL);
|
||||
free(sb);
|
||||
}
|
||||
return eldbus_message_method_return_new(msg);
|
||||
}
|
||||
|
||||
|
||||
static const Eldbus_Method tw_methods[] = {
|
||||
{ "LinkDetect", ELDBUS_ARGS({"s", "URI"}, {"u", "Timestamp"}), NULL, dbus_link_detect_cb },
|
||||
{ "LinkMouseIn", ELDBUS_ARGS({"s", "URI"}, {"u", "Timestamp"}, {"i", "X Coordinate"}, {"i", "Y Coordinate"}), NULL, dbus_link_mouse_in_cb },
|
||||
{ "LinkMouseOut", ELDBUS_ARGS({"s", "URI"}, {"u", "Timestamp"}, {"i", "X Coordinate"}, {"i", "Y Coordinate"}), NULL, dbus_link_mouse_out_cb },
|
||||
{ "LinkShow", ELDBUS_ARGS({"s", "URI"}), NULL, dbus_link_show_cb },
|
||||
{ "LinkHide", ELDBUS_ARGS({"s", "URI"}), NULL, dbus_link_hide_cb },
|
||||
{ "LinkOpen", ELDBUS_ARGS({"s", "URI"}), NULL, dbus_link_open_cb },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const Eldbus_Service_Interface_Desc tw_desc =
|
||||
{
|
||||
"org.enlightenment.wm.Teamwork", tw_methods, tw_signals
|
||||
};
|
||||
|
||||
static Eet_Data_Descriptor *
|
||||
media_cache_edd_new(void)
|
||||
{
|
||||
Eet_Data_Descriptor *edd;
|
||||
Eet_Data_Descriptor_Class eddc;
|
||||
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Media_Cache);
|
||||
edd = eet_data_descriptor_stream_new(&eddc);
|
||||
#define ADD(name, type) \
|
||||
EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Media_Cache, #name, name, EET_T_##type)
|
||||
|
||||
ADD(sha1, INLINED_STRING);
|
||||
ADD(timestamp, ULONG_LONG);
|
||||
#undef ADD
|
||||
return edd;
|
||||
}
|
||||
|
||||
static int
|
||||
media_cache_compare(Media_Cache *a, Media_Cache *b)
|
||||
{
|
||||
long long diff;
|
||||
diff = a->timestamp - b->timestamp;
|
||||
if (diff < 0) return -1;
|
||||
if (!diff) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
media_cache_add(const char *sha1, unsigned long long timestamp)
|
||||
{
|
||||
Media_Cache *ic;
|
||||
if (!tw_cache_list) return;
|
||||
ic = malloc(sizeof(Media_Cache));
|
||||
ic->sha1 = eina_stringshare_ref(sha1);
|
||||
ic->timestamp = timestamp;
|
||||
tw_cache_list->cache = eina_list_sorted_insert(tw_cache_list->cache, (Eina_Compare_Cb)media_cache_compare, ic);
|
||||
}
|
||||
|
||||
static void
|
||||
media_cache_del(const char *sha1)
|
||||
{
|
||||
Eina_List *l, *l2;
|
||||
Media_Cache *ic;
|
||||
|
||||
if (!tw_cache_list) return;
|
||||
EINA_LIST_FOREACH_SAFE(tw_cache_list->cache, l, l2, ic)
|
||||
{
|
||||
if (ic->sha1 == sha1) continue;
|
||||
tw_cache_list->cache = eina_list_remove_list(tw_cache_list->cache, l);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
media_cache_update(const char *sha1, unsigned long long timestamp)
|
||||
{
|
||||
Media_Cache *ic;
|
||||
Eina_List *l;
|
||||
|
||||
if (!tw_cache_list) return;
|
||||
EINA_LIST_FOREACH(tw_cache_list->cache, l, ic)
|
||||
{
|
||||
if (ic->sha1 != sha1) continue;
|
||||
ic->timestamp = timestamp;
|
||||
break;
|
||||
}
|
||||
tw_cache_list->cache = eina_list_sort(tw_cache_list->cache, eina_list_count(tw_cache_list->cache), (Eina_Compare_Cb)media_cache_compare);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
media_cleaner_cb(void *data EINA_UNUSED)
|
||||
{
|
||||
unsigned long long now;
|
||||
Media_Cache *ic;
|
||||
Eina_List *l, *l2;
|
||||
int cleaned = 0;
|
||||
if ((!cleaner_edd) || (!cache_edd) || (tw_config->allowed_media_age < 0) || (!tw_cache_list) || (!tw_cache_list->cache))
|
||||
{
|
||||
media_cleaner = NULL;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
if (tw_config->allowed_media_age)
|
||||
{
|
||||
now = (unsigned long long)ecore_time_unix_get();
|
||||
now -= tw_config->allowed_media_age * 24 * 60 * 60;
|
||||
}
|
||||
else
|
||||
now = ULONG_LONG_MAX;
|
||||
EINA_LIST_FOREACH_SAFE(tw_cache_list->cache, l, l2, ic)
|
||||
{
|
||||
/* only clean up to 3 entries at a time to ensure responsiveness */
|
||||
if (cleaned >= 3) break;
|
||||
if (ic->timestamp >= now)
|
||||
{
|
||||
/* stop the idler for now to avoid pointless spinning */
|
||||
ecore_timer_add(24 * 60 * 60, (Ecore_Task_Cb)tw_idler_start, NULL);
|
||||
media_cleaner = NULL;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
eet_delete(media, ic->sha1);
|
||||
tw_cache_list->cache = eina_list_remove_list(tw_cache_list->cache, l);
|
||||
eina_stringshare_del(ic->sha1);
|
||||
free(ic);
|
||||
cleaned++;
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
tw_dummy_add(const char *url)
|
||||
{
|
||||
if (!dummies) return;
|
||||
eet_write(dummies, url, "0", 1, 0);
|
||||
INF("Added new dummy for url %s", url);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
tw_dummy_check(const char *url)
|
||||
{
|
||||
char **list;
|
||||
int lsize;
|
||||
|
||||
if (!dummies) return EINA_FALSE;
|
||||
list = eet_list(dummies, url, &lsize);
|
||||
if (lsize)
|
||||
{
|
||||
free(list);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
tw_media_add(const char *url, Eina_Binbuf *buf, unsigned long long timestamp)
|
||||
{
|
||||
const char *sha1;
|
||||
int lsize;
|
||||
char **list;
|
||||
|
||||
if (!media) return -1;
|
||||
if (!tw_config->allowed_media_age) return 0; //disk caching disabled
|
||||
|
||||
sha1 = sha1_encode(eina_binbuf_string_get(buf), eina_binbuf_length_get(buf));
|
||||
INF("Media: %s - %s", url, sha1);
|
||||
|
||||
list = eet_list(media, url, &lsize);
|
||||
if (lsize)
|
||||
{
|
||||
eina_stringshare_del(sha1);
|
||||
free(list);
|
||||
return -1; /* should never happen */
|
||||
}
|
||||
list = eet_list(media, sha1, &lsize);
|
||||
if (lsize)
|
||||
{
|
||||
eet_alias(media, url, sha1, 0);
|
||||
eet_sync(media);
|
||||
INF("Added new alias for image %s", sha1);
|
||||
eina_stringshare_del(sha1);
|
||||
free(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
eet_write(media, sha1, eina_binbuf_string_get(buf), eina_binbuf_length_get(buf), 1);
|
||||
eet_alias(media, url, sha1, 0);
|
||||
eet_sync(media);
|
||||
media_cache_add(sha1, timestamp);
|
||||
INF("Added new media with length %zu: %s", eina_binbuf_length_get(buf), sha1);
|
||||
eina_stringshare_del(sha1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
tw_media_del(const char *url)
|
||||
{
|
||||
const char *alias;
|
||||
if (!media) return;
|
||||
alias = eet_alias_get(media, url);
|
||||
eet_delete(media, alias);
|
||||
media_cache_del(alias);
|
||||
eina_stringshare_del(alias);
|
||||
}
|
||||
|
||||
static Eina_Binbuf *
|
||||
tw_media_get(const char *url, unsigned long long timestamp)
|
||||
{
|
||||
size_t size;
|
||||
unsigned char *img;
|
||||
Eina_Binbuf *buf = NULL;
|
||||
const char *alias;
|
||||
char **list;
|
||||
int lsize;
|
||||
|
||||
if (!media) return NULL;
|
||||
|
||||
list = eet_list(media, url, &lsize);
|
||||
if (!lsize) return NULL;
|
||||
free(list);
|
||||
|
||||
img = eet_read(media, url, (int*)&size);
|
||||
alias = eet_alias_get(media, url);
|
||||
buf = eina_binbuf_manage_new_length(img, size);
|
||||
media_cache_update(alias, timestamp);
|
||||
|
||||
eina_stringshare_del(alias);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
tw_media_ping(const char *url, unsigned long long timestamp)
|
||||
{
|
||||
const char *alias;
|
||||
|
||||
if (!media) return;
|
||||
|
||||
alias = eet_alias_get(media, url);
|
||||
media_cache_update(alias, timestamp);
|
||||
|
||||
eina_stringshare_del(alias);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
tw_idler_start(void)
|
||||
{
|
||||
if (!media) return EINA_FALSE;
|
||||
media_cleaner = ecore_idler_add((Ecore_Task_Cb)media_cleaner_cb, NULL);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
tw_popup_del(void *obj)
|
||||
{
|
||||
eina_stringshare_del(e_object_data_get(obj));
|
||||
}
|
||||
|
||||
EINTERN void
|
||||
tw_popup_opacity_set(void)
|
||||
{
|
||||
if (tw_mod->pop && tw_mod->pop->cw)
|
||||
e_comp_win_opacity_set(tw_mod->pop->cw, lround((double)255 * (tw_config->popup_opacity / 100.)));
|
||||
}
|
||||
|
||||
static void
|
||||
tw_show_helper(Evas_Object *o, int w, int h)
|
||||
{
|
||||
int px, py, pw, ph;
|
||||
double ratio = tw_config->popup_size / 100.;
|
||||
|
||||
E_FREE_FUNC(tw_mod->pop, e_object_del);
|
||||
tw_mod->sticky = 0;
|
||||
tw_mod->pop = e_popup_new(e_zone_current_get(e_util_container_current_get()), 0, 0, 1, 1);
|
||||
e_popup_ignore_events_set(tw_mod->pop, 1);
|
||||
pw = MIN(w, (ratio * (double)tw_mod->pop->zone->w));
|
||||
pw = MIN(pw, tw_mod->pop->zone->w);
|
||||
if (pw == w) ph = h;
|
||||
else
|
||||
ph = lround((double)(pw * h) / ((double)w));
|
||||
if (ph > tw_mod->pop->zone->h)
|
||||
{
|
||||
ph = tw_mod->pop->zone->h;
|
||||
pw = lround((double)(ph * w) / ((double)h));
|
||||
}
|
||||
e_widget_preview_size_set(o, pw, ph);
|
||||
e_widget_preview_vsize_set(o, w, h);
|
||||
e_popup_layer_set(tw_mod->pop, E_COMP_CANVAS_LAYER_POPUP, 0);
|
||||
|
||||
if ((last_coords.x == last_coords.y) && (last_coords.x == -1))
|
||||
{
|
||||
px = lround(ratio * (double)tw_mod->pop->zone->w) - (pw / 2);
|
||||
py = lround(ratio * (double)tw_mod->pop->zone->h) - (ph / 2);
|
||||
if (px + pw > tw_mod->pop->zone->w)
|
||||
px = tw_mod->pop->zone->w - pw;
|
||||
if (py + ph > tw_mod->pop->zone->h)
|
||||
py = tw_mod->pop->zone->h - ph;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* prefer tooltip left of last_coords */
|
||||
px = last_coords.x - pw - 3;
|
||||
/* if it's offscreen, try right of last_coords */
|
||||
if (px < 0) px = last_coords.x + 3;
|
||||
/* fuck this, stick it right on the last_coords */
|
||||
if (px + pw + 3 > tw_mod->pop->zone->w)
|
||||
px = (last_coords.x / 2) - (pw / 2);
|
||||
/* give up */
|
||||
if (px < 0) px = 0;
|
||||
|
||||
/* prefer tooltip above last_coords */
|
||||
py = last_coords.y - ph - 3;
|
||||
/* if it's offscreen, try below last_coords */
|
||||
if (py < 0) py = last_coords.y + 3;
|
||||
/* fuck this, stick it right on the last_coords */
|
||||
if (py + ph + 3 > tw_mod->pop->zone->h)
|
||||
py = (last_coords.y / 2) - (ph / 2);
|
||||
/* give up */
|
||||
if (py < 0) py = 0;
|
||||
}
|
||||
e_popup_move_resize(tw_mod->pop, px, py, pw, ph);
|
||||
e_popup_content_set(tw_mod->pop, o);
|
||||
e_popup_show(tw_mod->pop);
|
||||
tw_popup_opacity_set();
|
||||
E_OBJECT_DEL_SET(tw_mod->pop, tw_popup_del);
|
||||
}
|
||||
|
||||
static void
|
||||
tw_show(Media *i)
|
||||
{
|
||||
Evas_Object *o, *ic, *prev;
|
||||
int w, h;
|
||||
|
||||
if (!i->buf) i->buf = tw_media_get(i->addr, ecore_time_unix_get());
|
||||
if (!i->buf) return;
|
||||
prev = e_widget_preview_add(e_util_comp_current_get()->evas, 50, 50);
|
||||
o = evas_object_image_filled_add(e_widget_preview_evas_get(prev));
|
||||
evas_object_image_memfile_set(o, (void*)eina_binbuf_string_get(i->buf), eina_binbuf_length_get(i->buf), NULL, NULL);
|
||||
evas_object_image_size_get(o, &w, &h);
|
||||
ic = e_icon_add(e_widget_preview_evas_get(prev));
|
||||
e_icon_image_object_set(ic, o);
|
||||
e_widget_preview_extern_object_set(prev, ic);
|
||||
tw_show_helper(prev, w, h);
|
||||
e_object_data_set(E_OBJECT(tw_mod->pop), eina_stringshare_ref(i->addr));
|
||||
e_popup_object_add(tw_mod->pop, ic);
|
||||
}
|
||||
|
||||
static void
|
||||
tw_show_local_dir(const char *uri)
|
||||
{
|
||||
E_Action *act;
|
||||
|
||||
act = e_action_find("fileman");
|
||||
if (act) act->func.go(NULL, uri);
|
||||
}
|
||||
|
||||
static void
|
||||
tw_show_local_file(const char *uri)
|
||||
{
|
||||
Evas_Object *o, *prev;
|
||||
int w, h;
|
||||
|
||||
if (!evas_object_image_extension_can_load_get(uri)) return;
|
||||
prev = e_widget_preview_add(e_util_comp_current_get()->evas, 50, 50);
|
||||
o = e_icon_add(e_widget_preview_evas_get(prev));
|
||||
e_icon_file_set(o, uri);
|
||||
e_icon_preload_set(o, 1);
|
||||
e_icon_size_get(o, &w, &h);
|
||||
e_widget_preview_extern_object_set(prev, o);
|
||||
tw_show_helper(prev, w, h);
|
||||
e_popup_object_add(tw_mod->pop, o);
|
||||
e_object_data_set(E_OBJECT(tw_mod->pop), eina_stringshare_add(uri));
|
||||
}
|
||||
|
||||
EINTERN Eina_Bool
|
||||
tw_hide(void *d EINA_UNUSED)
|
||||
{
|
||||
E_FREE_FUNC(tw_mod->pop, e_object_del);
|
||||
last_coords.x = last_coords.y = 0;
|
||||
E_FREE_FUNC(tw_hide_timer, ecore_timer_del);
|
||||
download_media_cleanup();
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EINTERN int
|
||||
e_tw_init(void)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
Eet_Data_Descriptor_Class eddc;
|
||||
|
||||
tw_dbus_iface = e_msgbus_interface_attach(&tw_desc);
|
||||
|
||||
e_user_dir_concat_static(buf, "images/cache.eet");
|
||||
media = eet_open(buf, EET_FILE_MODE_READ_WRITE);
|
||||
if (!media)
|
||||
{
|
||||
ERR("Could not open media cache file!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cache_edd = media_cache_edd_new();
|
||||
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Media_Cache_List);
|
||||
cleaner_edd = eet_data_descriptor_file_new(&eddc);
|
||||
EET_DATA_DESCRIPTOR_ADD_LIST(cleaner_edd, Media_Cache_List, "cache", cache, cache_edd);
|
||||
tw_cache_list = eet_data_read(media, cleaner_edd, "media_cache");
|
||||
|
||||
e_user_dir_concat_static(buf, "images/dummies.eet");
|
||||
dummies = eet_open(buf, EET_FILE_MODE_READ_WRITE);
|
||||
|
||||
E_LIST_HANDLER_APPEND(handlers, ECORE_CON_EVENT_URL_COMPLETE, download_media_complete, tw_mod);
|
||||
E_LIST_HANDLER_APPEND(handlers, ECORE_CON_EVENT_URL_PROGRESS, download_media_status, tw_mod);
|
||||
E_LIST_HANDLER_APPEND(handlers, ECORE_CON_EVENT_URL_DATA, download_media_data, tw_mod);
|
||||
|
||||
tw_mod->media = eina_hash_string_superfast_new((Eina_Free_Cb)download_media_free);
|
||||
return 1;
|
||||
}
|
||||
|
||||
EINTERN void
|
||||
e_tw_shutdown(void)
|
||||
{
|
||||
E_FREE_LIST(handlers, ecore_event_handler_del);
|
||||
if (media)
|
||||
{
|
||||
if (tw_cache_list)
|
||||
{
|
||||
Media_Cache *ic;
|
||||
eet_data_write(media, cleaner_edd, "media_cache", tw_cache_list, 1);
|
||||
EINA_LIST_FREE(tw_cache_list->cache, ic)
|
||||
{
|
||||
eina_stringshare_del(ic->sha1);
|
||||
free(ic);
|
||||
}
|
||||
free(tw_cache_list);
|
||||
}
|
||||
E_FREE_FUNC(media, eet_close);
|
||||
}
|
||||
E_FREE_FUNC(tw_dbus_iface, eldbus_service_interface_unregister);
|
||||
E_FREE_FUNC(dummies, eet_close);
|
||||
E_FREE_FUNC(cleaner_edd, eet_data_descriptor_free);
|
||||
E_FREE_FUNC(cache_edd, eet_data_descriptor_free);
|
||||
tw_hide(NULL);
|
||||
last_coords.x = last_coords.y = 0;
|
||||
eina_hash_free(tw_mod->media);
|
||||
E_FREE_FUNC(tw_mod->pop, e_object_del);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
[Desktop Entry]
|
||||
Type=Link
|
||||
Name=Teamwork
|
||||
Icon=e-module-teamwork
|
||||
Comment=Enlightenment Is A Team Player
|
||||
X-Enlightenment-ModuleType=core
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is SHA 180-1 Reference Implementation (Compact version)
|
||||
*
|
||||
* The Initial Developer of the Original Code is Paul Kocher of
|
||||
* Cryptography Research. Portions created by Paul Kocher are
|
||||
* Copyright (C) 1995-9 by Cryptography Research, Inc. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Paul Kocher
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sha1.h"
|
||||
|
||||
static void shaHashBlock(SHA_CTX2 *ctx);
|
||||
|
||||
void
|
||||
SHA1_Init2(SHA_CTX2 *ctx) {
|
||||
int i;
|
||||
|
||||
ctx->lenW = 0;
|
||||
ctx->sizeHi = ctx->sizeLo = 0;
|
||||
|
||||
/* Initialize H with the magic constants (see FIPS180 for constants)
|
||||
*/
|
||||
ctx->H[0] = 0x67452301;
|
||||
ctx->H[1] = 0xefcdab89;
|
||||
ctx->H[2] = 0x98badcfe;
|
||||
ctx->H[3] = 0x10325476;
|
||||
ctx->H[4] = 0xc3d2e1f0;
|
||||
|
||||
for (i = 0; i < 80; i++)
|
||||
ctx->W[i] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
SHA1_Update2(SHA_CTX2 *ctx,
|
||||
void *_dataIn,
|
||||
int len) {
|
||||
unsigned char *dataIn = _dataIn;
|
||||
int i;
|
||||
|
||||
/* Read the data into W and process blocks as they get full
|
||||
*/
|
||||
for (i = 0; i < len; i++) {
|
||||
ctx->W[ctx->lenW / 4] <<= 8;
|
||||
ctx->W[ctx->lenW / 4] |= (unsigned int)dataIn[i];
|
||||
if ((++ctx->lenW) % 64 == 0)
|
||||
{
|
||||
shaHashBlock(ctx);
|
||||
ctx->lenW = 0;
|
||||
}
|
||||
ctx->sizeLo += 8;
|
||||
ctx->sizeHi += (ctx->sizeLo < 8);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SHA1_Final2(unsigned char hashout[20],
|
||||
SHA_CTX2 *ctx) {
|
||||
unsigned char pad0x80 = 0x80;
|
||||
unsigned char pad0x00 = 0x00;
|
||||
unsigned char padlen[8];
|
||||
int i;
|
||||
|
||||
/* Pad with a binary 1 (e.g. 0x80), then zeroes, then length
|
||||
*/
|
||||
padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255);
|
||||
padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255);
|
||||
padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255);
|
||||
padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255);
|
||||
padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255);
|
||||
padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255);
|
||||
padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255);
|
||||
padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255);
|
||||
SHA1_Update2(ctx, &pad0x80, 1);
|
||||
while (ctx->lenW != 56)
|
||||
SHA1_Update2(ctx, &pad0x00, 1);
|
||||
SHA1_Update2(ctx, padlen, 8);
|
||||
|
||||
/* Output hash
|
||||
*/
|
||||
for (i = 0; i < 20; i++) {
|
||||
hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24);
|
||||
ctx->H[i / 4] <<= 8;
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-initialize the context (also zeroizes contents)
|
||||
*/
|
||||
SHA1_Init2(ctx);
|
||||
}
|
||||
|
||||
#define SHA_ROT(X, n) (((X) << (n)) | ((X) >> (32 - (n))))
|
||||
|
||||
static void
|
||||
shaHashBlock(SHA_CTX2 *ctx) {
|
||||
int t;
|
||||
unsigned int A, B, C, D, E, TEMP;
|
||||
|
||||
for (t = 16; t <= 79; t++)
|
||||
ctx->W[t] =
|
||||
SHA_ROT(ctx->W[t - 3] ^ ctx->W[t - 8] ^ ctx->W[t - 14] ^ ctx->W[t - 16], 1);
|
||||
|
||||
A = ctx->H[0];
|
||||
B = ctx->H[1];
|
||||
C = ctx->H[2];
|
||||
D = ctx->H[3];
|
||||
E = ctx->H[4];
|
||||
|
||||
for (t = 0; t <= 19; t++) {
|
||||
TEMP = SHA_ROT(A, 5) + (((C ^ D) & B) ^ D) + E + ctx->W[t] + 0x5a827999;
|
||||
E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
|
||||
}
|
||||
for (t = 20; t <= 39; t++) {
|
||||
TEMP = SHA_ROT(A, 5) + (B ^ C ^ D) + E + ctx->W[t] + 0x6ed9eba1;
|
||||
E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
|
||||
}
|
||||
for (t = 40; t <= 59; t++) {
|
||||
TEMP = SHA_ROT(A, 5) + ((B & C) | (D & (B | C))) + E + ctx->W[t] + 0x8f1bbcdc;
|
||||
E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
|
||||
}
|
||||
for (t = 60; t <= 79; t++) {
|
||||
TEMP = SHA_ROT(A, 5) + (B ^ C ^ D) + E + ctx->W[t] + 0xca62c1d6;
|
||||
E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
|
||||
}
|
||||
|
||||
ctx->H[0] += A;
|
||||
ctx->H[1] += B;
|
||||
ctx->H[2] += C;
|
||||
ctx->H[3] += D;
|
||||
ctx->H[4] += E;
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is SHA 180-1 Header File
|
||||
*
|
||||
* The Initial Developer of the Original Code is Paul Kocher of
|
||||
* Cryptography Research. Portions created by Paul Kocher are
|
||||
* Copyright (C) 1995-9 by Cryptography Research, Inc. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Paul Kocher
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#ifndef SHA_H
|
||||
#define SHA_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned int H[5];
|
||||
unsigned int W[80];
|
||||
int lenW;
|
||||
unsigned int sizeHi,sizeLo;
|
||||
} SHA_CTX2;
|
||||
|
||||
void SHA1_Init2(SHA_CTX2 *ctx);
|
||||
void SHA1_Update2(SHA_CTX2 *ctx, void *dataIn, int len);
|
||||
void SHA1_Final2(unsigned char hashout[20], SHA_CTX2 *ctx);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue