Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Zielke <kg4gjy@takeovertheworld.org>2009-05-26 05:05:34 (GMT)
committer Jack Zielke <kg4gjy@takeovertheworld.org>2009-05-26 05:05:34 (GMT)
commit9ada452201520759bd6ec5e46a5064f5c63e638f (patch)
tree2779e194d10d26b815f9ba4bba99c0d96bce3144
version 1 - no journal, no messaging
-rw-r--r--COPYING339
-rw-r--r--MANIFEST14
-rw-r--r--NEWS2
-rw-r--r--README8
-rw-r--r--TODO11
-rw-r--r--activity/activity-aprs.svg48
-rw-r--r--activity/activity.info6
-rwxr-xr-xaprs.py928
-rw-r--r--locale/en/LC_MESSAGES/org.laptop.APRS.mobin0 -> 404 bytes
-rw-r--r--locale/en/activity.linfo2
-rwxr-xr-xsetup.py3
11 files changed, 1361 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/MANIFEST b/MANIFEST
new file mode 100644
index 0000000..6750e8e
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,14 @@
+NEWS
+TODO
+setup.py
+COPYING
+README
+locale
+locale/en
+locale/en/LC_MESSAGES
+locale/en/LC_MESSAGES/org.laptop.APRS.mo
+locale/en/activity.linfo
+activity
+activity/activity-aprs.svg
+activity/activity.info
+aprs.py
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..6929339
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,2 @@
+September 14 2008 - version 0 started
+September 20 2008 - version 1 - no journal, no messaging
diff --git a/README b/README
new file mode 100644
index 0000000..220de8a
--- /dev/null
+++ b/README
@@ -0,0 +1,8 @@
+APRS for OLPC
+
+APRS Position Reporting for OLPC
+
+This activity tries to follow the development plan outlined by Bob Bruninga,
+WB4APR.
+
+http://www.ew.usna.edu/~bruninga/APRS-OLPC.html
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..cec5e21
--- /dev/null
+++ b/TODO
@@ -0,0 +1,11 @@
+save in journal
+
+send messages
+multi language
+
+cleanup timers on disconnect
+cleanup old acks in self.sent_acks{}
+cleanup old timers in self.timers[]
+
+auto reconnect?
+aprs.laptop.org?
diff --git a/activity/activity-aprs.svg b/activity/activity-aprs.svg
new file mode 100644
index 0000000..ee2fd3f
--- /dev/null
+++ b/activity/activity-aprs.svg
@@ -0,0 +1,48 @@
+<?xml version="1.0" ?><!-- Created with Inkscape (http://www.inkscape.org/) --><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#000000">
+ <!ENTITY fill_color "#666666">
+]><svg height="55px" id="svg3737" version="1.0" width="55px" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
+ <defs id="defs3"/>
+ <g id="layer1">
+ <path d="M 8.906382,7.3606237 C 8.906382,7.7322009 10.647913,9.7722576 11.049239,10.574911 C 11.542539,11.56151 12.108364,12.668553 12.299239,13.432053 C 12.588773,14.590189 12.942075,15.753429 13.370667,16.824911 C 13.829335,17.971579 13.769986,19.136472 14.084953,20.396339 C 14.375579,21.558844 14.416031,22.944583 14.620667,23.967768 C 14.838883,25.058846 14.97781,26.006522 14.97781,27.182053 C 14.97781,28.297644 15.156382,29.571657 15.156382,30.753482 C 15.156382,32.003482 15.156382,33.253482 15.156382,34.503482 C 15.156382,35.813006 15.156382,37.122529 15.156382,38.432053 C 15.156382,39.741577 15.156382,41.051101 15.156382,42.360625 C 15.156382,43.610625 15.156382,44.860625 15.156382,46.110625 C 15.156382,47.182053 15.156382,48.253482 15.156382,49.32491" id="path3341" style="fill:none;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:3.5px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
+ <path d="M 14.904323,48.653767 C 15.700637,49.440116 16.935789,47.653227 18.028322,47.383512 C 18.995158,47.144827 20.077246,47.285987 21.152322,47.020582 C 22.158165,46.772267 23.117551,46.657652 24.27632,46.657652 C 25.440163,46.657652 26.604006,46.657652 27.767849,46.657652 C 29.054201,46.657652 30.340554,46.657652 31.626906,46.657652 C 32.790749,46.657652 33.954592,46.657652 35.118435,46.657652 C 36.221024,46.657652 37.323611,46.657652 38.4262,46.657652 C 39.730935,46.657652 40.962923,46.639886 42.101492,47.202046 C 43.097595,47.693864 44.440498,48.084717 45.225492,48.472302 C 45.974476,48.842108 46.680364,49.044432 47.614432,49.198162" id="path3355" style="fill:none;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:3.5px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
+ <path d="M 47.385984,49.759824 C 47.245209,49.467002 47.385984,47.538833 47.385984,46.636601 C 47.385984,45.364178 47.385984,44.091755 47.385984,42.81933 C 47.385984,41.778255 47.385984,40.737183 47.385984,39.696108 C 47.385984,38.539359 47.385984,37.38261 47.385984,36.225861 C 47.385984,34.66425 47.385984,33.102639 47.385984,31.541027 C 47.385984,29.870535 47.052321,28.335622 47.052321,26.682681 C 47.052321,25.489221 46.885489,24.415814 46.885489,23.212435 C 46.885489,22.112167 46.466348,20.427662 46.218163,19.395163 C 45.834003,17.796986 45.427111,16.277757 45.050343,14.710331 C 44.686443,13.196442 43.768911,11.812245 43.215194,10.37252 C 42.720272,9.0856606 42.001614,8.2581449 41.546881,7.0757851 C 41.343637,6.5473323 41.10997,6.3941768 40.879553,6.034711" id="path3359" style="fill:none;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:3.5px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
+ <path d="M 41.049239,6.1106237 C 40.612213,5.8921109 39.06339,5.0391951 38.370667,5.0391951 C 37.120667,5.0391951 35.870667,5.0391951 34.620667,5.0391951 C 33.311144,5.0391951 32.00162,5.0391951 30.692096,5.0391951 C 29.561144,5.0391951 28.430191,5.0391951 27.299239,5.0391951 C 26.108763,5.0391951 24.918286,5.0391951 23.72781,5.0391951 C 22.436892,5.0391951 21.010348,4.9149893 19.799239,5.2177665 C 18.651054,5.5048128 17.460443,5.5069543 16.22781,5.7534808 C 14.915446,6.0159537 13.595961,6.1435859 12.299239,6.4677665 C 11.148647,6.7554146 7.755789,7.8268432 8.906382,7.5391951 C 8.906382,7.7266304 7.780583,9.5423906 7.656382,10.039196 C 7.459305,10.827502 7.299239,11.598257 7.299239,12.539196 C 7.299239,13.432053 7.299239,14.324911 7.299239,15.217768 C 7.299239,15.396339 7.299239,15.574911 7.299239,15.753482 C 7.299239,16.860689 8.987494,14.284354 9.97781,13.789196 C 10.770011,13.393096 10.967804,13.074911 11.942096,13.074911" id="path3361" style="fill:none;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:3.5px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
+ <path d="M 37.393565,13.673909 C 37.02255,13.659039 36.650922,13.659459 36.279629,13.658184 C 35.878539,13.684946 35.462607,13.60819 35.06898,13.699057 C 34.972075,13.741171 34.861616,13.732612 34.763033,13.767224 C 34.675573,13.797931 34.336647,14.029274 34.526348,13.922091 C 35.233378,13.522612 37.361914,12.339424 36.636672,12.704798 C 35.819855,13.116307 35.046379,13.608728 34.251233,14.060693 C 38.081726,11.679303 36.40704,12.764261 35.619583,13.469462 C 35.30119,13.758367 35.005755,14.080418 34.740789,14.419444 C 34.503671,14.767064 34.289492,15.127504 34.044787,15.470249 C 33.778453,15.805317 33.51831,16.145022 33.258685,16.485399 C 32.958038,16.903882 32.659942,17.324479 32.351557,17.737289 C 32.080909,18.113653 31.796902,18.480246 31.534921,18.862764 C 31.233862,19.309525 30.940206,19.75967 30.620048,20.193185 C 30.287598,20.648459 29.920258,21.07325 29.608498,21.543519 C 29.409373,21.860623 29.169345,22.148499 28.928784,22.434327 L 26.563952,23.434702 C 26.805292,23.160319 27.046519,22.884203 27.247071,22.577669 C 27.560131,22.10386 27.906105,21.660835 28.258596,21.215862 C 28.566331,20.780044 28.888024,20.354981 29.168004,19.899984 C 29.417777,19.50571 29.70517,19.138758 29.973094,18.756934 C 30.297867,18.358037 30.591546,17.933899 30.8852,17.512729 C 31.124952,17.164513 31.383225,16.828702 31.653659,16.503997 C 31.909245,16.163359 32.150315,15.819215 32.363503,15.450199 C 32.605265,15.081993 32.917503,14.772917 33.207746,14.443867 C 33.36767,14.318411 33.499908,14.16882 33.656817,14.040981 C 34.453461,13.391924 35.509394,13.002935 36.297004,12.425808 C 35.59491,12.831779 33.485038,14.043418 34.190722,13.643722 C 35.277831,13.027987 36.014146,12.276604 37.163732,12.136342 C 37.567941,12.124193 37.972468,12.13808 38.376807,12.134495 C 38.762539,12.133182 39.148545,12.13315 39.534031,12.118769 L 37.393565,13.673909 z" id="path3375" style="fill:&fill_color;;fill-opacity:1"/>
+ <path d="M 27.696413,12.239847 C 28.010042,12.181171 28.328351,12.158723 28.646504,12.142873 C 29.061391,12.134862 29.476339,12.131634 29.891292,12.129988 C 30.296564,12.164465 30.57069,12.421281 30.870383,12.661989 C 31.231942,12.959963 31.486963,13.348629 31.765959,13.717918 C 32.12886,14.180378 32.44753,14.672539 32.774351,15.160232 C 32.990665,15.531635 33.223071,15.891449 33.430514,16.26792 C 33.678467,16.647995 33.849386,17.068966 34.038581,17.479569 C 34.204955,17.879716 34.304382,18.301913 34.445364,18.711475 C 34.603158,19.112077 34.770812,19.509776 34.985301,19.883581 C 35.181193,20.250998 35.461951,20.562844 35.745918,20.863824 C 36.089132,21.244292 36.515032,21.50589 36.997305,21.667072 C 37.344619,21.764387 37.706856,21.773423 38.064935,21.781577 L 35.957603,23.299206 C 35.582515,23.2764 35.202302,23.248566 34.848314,23.111484 C 34.354989,22.899734 33.912908,22.604025 33.54309,22.211385 C 33.230187,21.906202 32.935913,21.57436 32.737399,21.181449 C 32.512358,20.794106 32.344244,20.379575 32.176928,19.964707 C 32.035296,19.562283 31.9182,19.156597 31.78442,18.752301 C 31.602063,18.347458 31.419543,17.938677 31.179804,17.564119 C 30.968467,17.196628 30.745397,16.837927 30.550966,16.461104 C 30.235675,15.972006 29.939001,15.472883 29.548149,15.037542 C 29.275759,14.688511 29.020397,14.325937 28.670431,14.046258 C 28.403508,13.840284 28.138857,13.655248 27.785964,13.66032 C 27.372831,13.660524 26.959,13.658562 26.546792,13.689987 C 26.227296,13.717013 25.90239,13.748355 25.601656,13.867255 L 27.696413,12.239847 z" id="path3377" style="fill:&fill_color;;fill-opacity:1"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3405" style="fill:&fill_color;;fill-opacity:1" transform="translate(68.72781,3.91948e-2)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3407" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(73.281382,-2.7286623)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3409" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(70.959954,-1.1215194)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3411" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(78.459953,-5.9429479)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3413" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(75.60281,-4.5143765)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3415" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(84.709953,-5.942948)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3417" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(81.674239,-6.3000908)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3419" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(88.281383,-8.9786617)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3421" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(87.567096,-6.1215193)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3423" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(87.209954,-10.764378)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3425" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(89.709953,-7.5500908)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3427" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(85.42424,-12.728661)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3429" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(84.174239,-14.514375)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3431" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(82.567097,-17.014376)"/>
+ <path d="M -48.928572,41.875 A 0.8035714,0.8035714 0 1 1 -50.535715,41.875 A 0.8035714,0.8035714 0 1 1 -48.928572,41.875 z" id="path3433" style="fill:&fill_color;;fill-opacity:1;display:inline" transform="translate(82.388525,-19.514375)"/>
+ <path d="M 43.541223,47.280861 L 40.594794,46.089357 L 33.005508,46.016261 C 25.51826,45.944148 24.502414,45.988407 19.951521,46.585021 C 18.014546,46.838955 17.61358,46.975002 16.649367,47.705427 C 16.345453,47.935653 16.011051,48.124018 15.906251,48.124018 C 15.774144,48.124018 15.689528,44.65995 15.630353,36.829375 C 15.579407,30.087666 15.470407,25.174816 15.359951,24.641875 C 15.258175,24.150804 14.962762,22.382946 14.70348,20.713304 C 14.351167,18.444591 13.989323,16.925202 13.271339,14.69972 C 12.195482,11.364966 11.794173,10.484472 10.629884,8.9042026 L 9.82326,7.8093914 L 11.101882,7.4358824 C 12.911282,6.9073324 13.642694,6.7614646 17.506396,6.1586074 L 20.93258,5.6240164 L 29.733289,5.6240164 C 37.239901,5.6240164 38.635024,5.6644396 39.221062,5.8989253 C 40.026191,6.2210753 40.572328,7.0854914 42.826883,11.606161 C 44.075799,14.110391 44.364103,14.882386 45.160991,17.856161 C 45.999896,20.986752 46.091583,21.531989 46.347082,24.909732 C 46.649898,28.91298 46.885851,48.484562 46.631207,48.476764 C 46.552249,48.474348 45.161758,47.936191 43.541223,47.280862 L 43.541223,47.280861 z M 19.576935,42.552587 C 19.916485,42.213041 19.837287,41.375521 19.445819,41.166014 C 18.976557,40.914871 18.793751,40.932714 18.464692,41.261773 C 17.897687,41.828773 18.223639,42.766875 18.987651,42.766875 C 19.193901,42.766875 19.45908,42.670446 19.576937,42.552589 L 19.576935,42.552587 z M 21.762648,41.368434 C 22.528462,40.748311 21.833828,39.690778 20.863066,39.998886 C 20.29835,40.178118 20.190155,40.974255 20.676942,41.368432 C 20.89906,41.548287 21.143341,41.695446 21.219794,41.695446 C 21.296248,41.695446 21.54053,41.548289 21.762646,41.368432 L 21.762648,41.368434 z M 24.084076,39.761291 C 24.849891,39.141168 24.155257,38.083636 23.184494,38.391743 C 22.619778,38.570975 22.511584,39.367112 22.998371,39.761289 C 23.220489,39.941145 23.464769,40.088303 23.541223,40.088303 C 23.617676,40.088303 23.861958,39.941146 24.084075,39.761289 L 24.084076,39.761291 z M 26.405505,37.975577 C 27.171319,37.355453 26.476685,36.297921 25.505923,36.606029 C 24.941207,36.785261 24.833012,37.581398 25.3198,37.975575 C 25.541917,38.15543 25.786198,38.302589 25.862651,38.302589 C 25.939105,38.302589 26.183387,38.155432 26.405503,37.975575 L 26.405505,37.975577 z M 29.262648,36.547005 C 30.028462,35.926882 29.333828,34.86935 28.363066,35.177457 C 27.79835,35.356689 27.690155,36.152827 28.176942,36.547004 C 28.39906,36.726859 28.643341,36.874018 28.719794,36.874018 C 28.796248,36.874018 29.04053,36.726861 29.262646,36.547004 L 29.262648,36.547005 z M 35.512648,36.547005 C 36.278462,35.926882 35.583828,34.86935 34.613066,35.177457 C 34.04835,35.356689 33.940155,36.152827 34.426942,36.547004 C 34.64906,36.726859 34.893341,36.874018 34.969794,36.874018 C 35.046248,36.874018 35.29053,36.726861 35.512646,36.547004 L 35.512648,36.547005 z M 38.369791,36.368434 C 39.135605,35.748311 38.440971,34.690779 37.470208,34.998886 C 36.905492,35.178118 36.797298,35.974255 37.284085,36.368432 C 37.506203,36.548287 37.750483,36.695446 37.826937,36.695446 C 37.903391,36.695446 38.147673,36.548289 38.369789,36.368432 L 38.369791,36.368434 z M 32.476933,36.189862 C 33.242748,35.569739 32.548114,34.512207 31.577351,34.820314 C 31.012635,34.999546 30.904441,35.795684 31.391228,36.189861 C 31.613346,36.369716 31.857626,36.516875 31.93408,36.516875 C 32.010533,36.516875 32.254816,36.369718 32.476932,36.189861 L 32.476933,36.189862 z M 40.512648,34.939862 C 41.278462,34.319739 40.583828,33.262207 39.613066,33.570314 C 39.048349,33.749546 38.940155,34.545684 39.426942,34.939861 C 39.64906,35.119716 39.893341,35.266875 39.969794,35.266875 C 40.046248,35.266875 40.29053,35.119718 40.512646,34.939861 L 40.512648,34.939862 z M 39.084076,33.511291 C 39.849891,32.891168 39.155257,31.833636 38.184494,32.141743 C 37.619778,32.320975 37.511583,33.117112 37.998371,33.511289 C 38.220489,33.691145 38.464769,33.838304 38.541223,33.838304 C 38.617676,33.838304 38.861958,33.691146 39.084074,33.511289 L 39.084076,33.511291 z M 38.012648,31.725577 C 38.778462,31.105454 38.083828,30.047921 37.113066,30.356029 C 36.548349,30.535261 36.440155,31.331398 36.926942,31.725575 C 37.14906,31.90543 37.393341,32.052589 37.469794,32.052589 C 37.546248,32.052589 37.79053,31.905432 38.012646,31.725575 L 38.012648,31.725577 z M 36.226933,29.761291 C 36.992748,29.141168 36.298114,28.083636 35.327351,28.391743 C 34.762635,28.570975 34.654441,29.367112 35.141228,29.761289 C 35.363346,29.941145 35.607626,30.088304 35.68408,30.088304 C 35.760533,30.088304 36.004816,29.941146 36.226932,29.761289 L 36.226933,29.761291 z M 34.976933,27.975577 C 35.742748,27.355454 35.048114,26.297921 34.077351,26.606029 C 33.512635,26.785261 33.404441,27.581398 33.891228,27.975575 C 34.113346,28.15543 34.357626,28.302589 34.43408,28.302589 C 34.510533,28.302589 34.754816,28.155432 34.976932,27.975575 L 34.976933,27.975577 z M 33.369791,25.475577 C 34.135605,24.855454 33.440971,23.797921 32.470208,24.106029 C 31.905492,24.285261 31.797298,25.081398 32.284085,25.475575 C 32.506203,25.65543 32.750483,25.802589 32.826937,25.802589 C 32.903391,25.802589 33.147673,25.655432 33.369789,25.475575 L 33.369791,25.475577 z M 27.892392,22.956139 C 28.927187,22.491857 29.182185,22.269232 30.096537,21.031823 C 30.665223,20.262211 31.259126,19.436329 31.416326,19.196529 L 31.702141,18.760527 L 31.931562,19.469059 C 32.057742,19.85875 32.30833,20.470843 32.488421,20.829264 L 32.815864,21.480936 L 32.377691,21.590913 C 31.733437,21.752609 31.577144,22.547727 32.105514,22.975575 C 32.625144,23.396343 32.758228,23.387532 33.24568,22.90008 L 33.648187,22.497573 L 34.353633,22.897141 C 35.354932,23.464288 35.918942,23.408748 37.036576,22.632946 C 38.074548,21.912445 38.214507,21.695446 37.641251,21.695446 C 37.047792,21.695446 35.915385,21.027434 35.44938,20.402452 C 35.210703,20.08235 34.794753,19.257946 34.52505,18.570446 C 34.255346,17.882946 33.921185,17.098686 33.782471,16.827646 C 33.54405,16.361779 33.568416,16.278821 34.228316,15.309789 C 35.272246,13.776829 35.526955,13.595575 36.485414,13.703607 C 37.312262,13.796804 37.808169,13.5662 39.255508,12.41547 L 39.701937,12.060529 L 38.312269,12.056563 C 37.503603,12.05425 36.667639,12.159123 36.312753,12.307404 C 35.537669,12.631252 33.580019,13.956613 33.080291,14.495829 L 32.698644,14.907634 L 31.936117,13.820582 C 30.937576,12.397064 30.360185,12.054107 28.960701,12.053257 C 27.932876,12.05263 27.792364,12.105179 26.773201,12.871297 C 26.174183,13.321588 25.68408,13.726038 25.68408,13.770075 C 25.68408,13.814114 26.256776,13.827391 26.956739,13.799582 L 28.229398,13.749018 L 29.166114,14.779657 C 29.681303,15.346507 30.283462,16.150802 30.504244,16.566979 L 30.905666,17.323663 L 29.070658,19.911339 C 28.061408,21.334563 27.087444,22.664911 26.906298,22.86767 C 26.596885,23.213995 26.485087,23.481161 26.649576,23.481161 C 26.68953,23.481161 27.248794,23.244902 27.892391,22.956139 L 27.892392,22.956139 z" id="path3472" style="fill:#ffffff;fill-opacity:1"/>
+ <path d="M 7.830475,13.811579 C 7.835882,12.078005 8.140585,10.338989 8.595909,9.4430596 L 9.007107,8.6339545 L 9.733294,9.6736296 C 10.132696,10.24545 10.663021,11.1173 10.911796,11.611072 L 11.364116,12.508838 L 10.568603,12.837866 C 10.131071,13.018832 9.335205,13.567097 8.800014,14.056232 L 7.826937,14.945568 L 7.830475,13.811579 z" id="path3474" style="fill:#ffffff;fill-opacity:1"/>
+ <path d="M 26.874718,23.185549 C 26.896662,23.136907 27.348332,22.506484 27.87843,21.784609 C 28.408529,21.062734 29.350432,19.756914 29.971548,18.882788 L 31.100853,17.293467 L 30.713363,16.632788 C 30.15679,15.683822 29.04226,14.254788 28.608739,13.934272 C 28.294054,13.701613 28.069197,13.658832 27.138427,13.654529 L 26.039615,13.649451 L 26.477115,13.275206 C 27.618674,12.298702 27.798025,12.224982 29.035823,12.223491 C 30.10669,12.222201 30.213523,12.245812 30.653903,12.581107 C 30.913233,12.778554 31.38736,13.307331 31.707515,13.756164 C 32.758238,15.229199 32.587073,15.154784 33.316329,14.455581 C 33.855277,13.938842 34.74985,13.358048 36.459418,12.414954 C 36.667722,12.300044 37.274142,12.214206 38.102115,12.182431 L 39.414615,12.132063 L 38.415035,12.864588 L 37.415454,13.597109 L 36.395335,13.640712 C 35.217868,13.691041 35.214464,13.693477 34.05454,15.316803 L 33.361659,16.286498 L 33.607665,16.703444 C 33.742967,16.932764 33.986862,17.508902 34.149652,17.983749 C 34.975507,20.392704 35.985713,21.572161 37.398544,21.776961 L 37.882473,21.847109 L 36.961827,22.503359 C 35.67392,23.421393 35.078043,23.391696 33.78504,22.345033 L 33.280464,21.936587 L 33.327129,22.336298 C 33.381534,22.802313 33.138038,23.065859 32.65307,23.065859 C 32.233005,23.065859 31.945865,22.769832 31.945865,22.336768 C 31.945865,21.909706 32.301493,21.627733 32.758365,21.692546 C 32.947428,21.719367 33.102115,21.730013 33.102115,21.716204 C 33.102115,21.702396 32.963689,21.443426 32.7945,21.140716 C 32.542118,20.689156 32.164174,19.767991 31.781982,18.672907 C 31.744613,18.565837 31.488788,18.836053 31.118142,19.374087 C 30.278905,20.592334 29.008132,22.249868 28.820862,22.370546 C 28.510602,22.570478 26.835784,23.271857 26.874719,23.185548 L 26.874718,23.185549 z" id="path3884" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 32.532307,25.501158 C 32.044373,25.234396 31.951193,24.709939 32.330708,24.366483 C 32.680668,24.049773 33.185308,24.104598 33.435548,24.486513 C 33.625654,24.776649 33.629492,24.848988 33.469679,25.129682 C 33.247099,25.520617 32.853328,25.676668 32.532305,25.501158 L 32.532307,25.501158 z" id="path3886" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 34.227115,28.064489 C 33.950778,27.978068 33.727115,27.650473 33.727115,27.332147 C 33.727115,26.647057 34.67683,26.400887 35.060548,26.986513 C 35.25065,27.276649 35.254492,27.348988 35.094679,27.629682 C 34.900163,27.971333 34.527099,28.158306 34.227115,28.064489 z" id="path3888" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 35.258365,29.718729 C 34.729134,29.345592 35.028094,28.406372 35.674458,28.411523 C 35.990164,28.414038 36.155967,28.533127 36.346154,28.893969 C 36.479715,29.147378 36.4669,29.238857 36.258577,29.518969 C 35.962228,29.917437 35.633353,29.983119 35.258365,29.718731 L 35.258365,29.718729 z" id="path3890" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 36.933987,31.556017 C 36.662589,31.256124 36.671429,30.873752 36.955708,30.616483 C 37.426148,30.190739 38.227115,30.507211 38.227115,31.118828 C 38.227115,31.703557 37.339184,32.003753 36.933989,31.556017 L 36.933987,31.556017 z" id="path3892" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 38.129932,33.465022 C 37.592867,33.088848 37.907392,32.159609 38.571779,32.159609 C 39.204842,32.159609 39.47573,33.096297 38.949302,33.465022 C 38.796508,33.572044 38.612145,33.659609 38.539615,33.659609 C 38.467085,33.659609 38.282725,33.572044 38.129929,33.465022 L 38.129932,33.465022 z" id="path3894" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 39.423947,34.794917 C 39.135684,34.476394 39.214433,34.053104 39.617755,33.753148 C 39.897868,33.544823 39.989347,33.532007 40.242755,33.665571 C 40.609517,33.858877 40.722735,34.021607 40.725202,34.358986 C 40.729593,34.959679 39.842114,35.256991 39.423944,34.794918 L 39.423947,34.794917 z" id="path3896" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 37.602115,36.447863 C 37.32494,36.348802 37.102115,36.023357 37.102115,35.717592 C 37.102115,35.086291 38.04431,34.793857 38.407528,35.312423 C 38.674489,35.693566 38.652825,35.870263 38.295297,36.227791 C 37.979339,36.543748 37.921653,36.562062 37.602115,36.447862 L 37.602115,36.447863 z" id="path3898" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 34.421703,36.381797 C 34.31468,36.228999 34.227115,36.003999 34.227115,35.881796 C 34.227115,35.583433 34.667263,35.159609 34.977115,35.159609 C 35.316349,35.159609 35.727115,35.593996 35.727115,35.952736 C 35.727115,36.604908 34.793019,36.911923 34.421703,36.381796 L 34.421703,36.381797 z" id="path3900" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 31.43399,36.056017 C 31.010019,35.587536 31.30077,34.878359 31.91681,34.878359 C 32.363152,34.878359 32.766264,35.331636 32.654888,35.708282 C 32.486237,36.278613 31.809793,36.471276 31.433989,36.056017 L 31.43399,36.056017 z" id="path3902" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 28.171703,36.381797 C 28.06468,36.228999 27.977115,36.003999 27.977115,35.881796 C 27.977115,35.583433 28.417263,35.159609 28.727115,35.159609 C 29.066349,35.159609 29.477115,35.593996 29.477115,35.952736 C 29.477115,36.604908 28.543019,36.911923 28.171703,36.381796 L 28.171703,36.381797 z" id="path3904" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 25.63235,38.023489 C 25.477103,37.964873 25.286312,37.776949 25.208368,37.605882 C 24.891147,36.909653 25.875817,36.314243 26.395242,36.888202 C 26.89948,37.445378 26.33318,38.288108 25.632349,38.023491 L 25.63235,38.023489 z" id="path3906" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 23.129928,39.715022 C 22.592867,39.338848 22.907392,38.409609 23.571779,38.409609 C 24.204842,38.409609 24.47573,39.346297 23.949302,39.715022 C 23.796504,39.822044 23.612145,39.909609 23.539615,39.909609 C 23.467085,39.909609 23.282725,39.822044 23.129929,39.715022 L 23.129928,39.715022 z" id="path3908" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 20.914615,41.385241 C 20.59033,41.201351 20.481385,41.032523 20.479029,40.710233 C 20.474698,40.117724 21.36092,39.810907 21.770242,40.263202 C 22.128442,40.659007 22.023873,41.123879 21.516583,41.390897 C 21.191792,41.561852 21.226643,41.562181 20.914615,41.385241 z" id="path3910" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 18.477115,42.409609 C 18.339615,42.272109 18.227115,42.047109 18.227115,41.909609 C 18.227115,41.772109 18.339615,41.547109 18.477115,41.409609 C 18.614615,41.272109 18.839615,41.159609 18.977115,41.159609 C 19.316349,41.159609 19.727115,41.593996 19.727115,41.952736 C 19.727115,42.586301 18.941095,42.873589 18.477115,42.409609 z" id="path3912" style="fill:&stroke_color;;fill-opacity:1"/>
+ <path d="M 43.614198,47.246769 L 40.926698,46.162434 L 31.864198,46.162434 C 23.891903,46.162434 22.636288,46.188412 21.426698,46.378386 C 20.670448,46.497162 19.560957,46.657451 18.96116,46.734591 C 18.078744,46.848076 17.732843,46.959187 17.14866,47.316797 C 16.751582,47.559871 16.286073,47.834757 16.114198,47.927652 L 15.801698,48.096554 L 15.773205,44.50449 C 15.757532,42.52886 15.687875,37.509309 15.61841,33.349934 C 15.49456,25.934031 15.485027,25.741395 15.126625,23.412434 C 14.478638,19.201687 14.120953,17.377266 13.686855,16.068695 C 13.453083,15.364001 13.0901,14.224934 12.880225,13.537434 C 12.383915,11.911645 11.672752,10.461459 10.65811,9.0061623 C 10.208085,8.3606935 9.8594153,7.8140885 9.8832903,7.791486 C 9.907164,7.7688823 10.517323,7.5778723 11.239198,7.3670198 C 12.546377,6.9852048 15.024239,6.4878323 16.926698,6.2253885 C 17.476698,6.149516 18.601698,5.975921 19.426698,5.839621 C 20.839689,5.606176 21.445124,5.5938498 29.864198,5.6271173 L 38.801698,5.6624335 L 39.696854,6.0820773 L 40.592012,6.501716 L 41.529134,8.2695773 C 42.044553,9.2418973 42.872153,10.909309 43.368247,11.974934 C 44.202088,13.766055 44.339114,14.186302 45.181922,17.537434 C 46.23915,21.741139 46.315007,22.227525 46.49037,25.927354 C 46.562445,27.448061 46.675618,29.163685 46.74186,29.739854 C 46.808103,30.316024 46.862728,34.738996 46.863249,39.568684 L 46.864198,48.349934 L 46.582948,48.340519 C 46.42826,48.335336 45.092323,47.843149 43.614198,47.246766 L 43.614198,47.246769 z M 19.534582,42.536694 C 19.822047,42.249227 19.894018,41.889694 19.72741,41.573405 C 19.531378,41.201256 19.37484,41.10418 18.96702,41.101847 C 18.631355,41.099926 18.114198,41.591472 18.114198,41.912434 C 18.114198,41.997016 18.23078,42.21443 18.37327,42.395576 C 18.668258,42.770594 19.232162,42.839114 19.53458,42.536694 L 19.534582,42.536694 z M 21.6284,41.467335 C 22.13575,41.195807 22.170755,40.392117 21.689235,40.070597 C 21.38957,39.870506 20.754887,39.972774 20.558785,40.252747 C 20.28456,40.64426 20.31629,40.93839 20.671017,41.293115 C 21.005509,41.627611 21.246857,41.671529 21.628399,41.467334 L 21.6284,41.467335 z M 24.114198,39.724934 C 24.417897,39.421235 24.437933,38.888596 24.157324,38.578526 C 23.899559,38.293697 23.271202,38.282224 22.96779,38.556807 C 22.469125,39.008091 22.867219,39.974934 23.551698,39.974934 C 23.723573,39.974934 23.976698,39.862434 24.114198,39.724934 z M 26.432378,37.918114 C 26.798389,37.552106 26.821315,37.22904 26.508677,36.842949 C 26.232865,36.502334 25.576978,36.458581 25.274912,36.760647 C 24.972845,37.062714 25.016598,37.7186 25.357213,37.994412 C 25.743304,38.307052 26.06637,38.284125 26.432379,37.918115 L 26.432378,37.918114 z M 29.355127,36.395576 C 29.690784,35.968856 29.681718,35.78109 29.307379,35.406752 C 28.904494,35.003864 28.451122,35.012495 28.12327,35.429291 C 27.7971,35.84395 27.796028,36.104621 28.119068,36.451364 C 28.476424,36.834944 29.029143,36.809996 29.355125,36.395576 L 29.355127,36.395576 z M 35.605127,36.395576 C 35.940784,35.968856 35.931718,35.78109 35.557379,35.406752 C 35.154494,35.003864 34.701122,35.012495 34.37327,35.429291 C 34.0471,35.84395 34.046028,36.104621 34.369068,36.451364 C 34.726424,36.834944 35.279143,36.809996 35.605125,36.395576 L 35.605127,36.395576 z M 38.34327,36.381184 C 38.959747,35.855986 38.619284,34.974934 37.799858,34.974934 C 37.058528,34.974934 36.742373,35.758587 37.260987,36.310627 C 37.584705,36.655211 37.99056,36.681669 38.34327,36.381184 z M 32.520448,36.124061 C 33.004607,35.70824 32.603884,34.724934 31.950268,34.724934 C 31.272319,34.724934 30.842969,35.699907 31.332948,36.126749 C 31.754118,36.49365 32.091007,36.492886 32.520448,36.12406 L 32.520448,36.124061 z M 40.282033,35.086151 C 40.687335,34.901481 40.891877,34.43901 40.742275,34.045529 C 40.496319,33.398617 39.675729,33.324046 39.289499,33.913507 C 39.022482,34.321032 39.146977,34.791851 39.584537,35.029269 C 40.004075,35.256907 39.921955,35.250211 40.282033,35.08615 L 40.282033,35.086151 z M 39.114198,33.474934 C 39.417897,33.171235 39.437933,32.638596 39.157324,32.328526 C 38.899559,32.043697 38.271202,32.032224 37.96779,32.306807 C 37.469125,32.758091 37.867219,33.724934 38.551698,33.724934 C 38.723573,33.724934 38.976698,33.612434 39.114198,33.474934 z M 37.8784,31.842335 C 38.449457,31.536712 38.436135,30.708194 37.855335,30.40785 C 37.439064,30.192591 36.953028,30.325387 36.746798,30.710732 C 36.542604,31.092276 36.586522,31.333621 36.921017,31.668115 C 37.255509,32.002611 37.496857,32.046529 37.878399,31.842334 L 37.8784,31.842335 z M 36.211385,29.780346 C 36.397352,29.650089 36.489198,29.457047 36.489198,29.196439 C 36.489198,28.675177 36.1723,28.349934 35.664413,28.349934 C 34.946059,28.349934 34.601147,29.211882 35.114198,29.724934 C 35.413885,30.024621 35.832452,30.045761 36.211384,29.780346 L 36.211385,29.780346 z M 34.965627,27.970062 C 35.507298,27.465421 35.162439,26.568684 34.426698,26.568684 C 33.654338,26.568684 33.336357,27.488239 33.943555,27.965861 C 34.358214,28.292031 34.618885,28.293104 34.965628,27.970064 L 34.965627,27.970062 z M 33.364198,25.474934 C 33.663193,25.175939 33.690764,24.569357 33.417769,24.296362 C 32.916273,23.794862 31.989198,24.197764 31.989198,24.917209 C 31.989198,25.24275 32.521604,25.724934 32.881055,25.724934 C 33.009284,25.724934 33.226698,25.612434 33.364198,25.474934 z M 28.614198,22.598342 C 29.037019,22.381407 29.566752,21.742885 31.021783,19.696321 L 31.708654,18.730206 L 32.047483,19.69632 C 32.233838,20.227682 32.486778,20.836499 32.609569,21.049245 L 32.832829,21.436054 L 32.4114,21.588447 C 31.727982,21.835572 31.665034,22.759201 32.308153,23.103389 C 32.588409,23.253376 32.678723,23.252216 32.955428,23.095066 C 33.132295,22.994619 33.338809,22.799934 33.41435,22.662434 C 33.489893,22.524934 33.565982,22.388775 33.58344,22.359857 C 33.600899,22.330941 33.741524,22.422349 33.89594,22.562987 C 34.568493,23.175527 35.461832,23.416951 36.087905,23.155361 C 36.541729,22.965741 37.979408,21.96553 37.985554,21.835142 C 37.987557,21.792631 37.758532,21.726912 37.476607,21.689099 C 36.805904,21.599137 35.907719,21.034761 35.422202,20.398205 C 35.208732,20.118326 34.875024,19.500781 34.680633,19.025884 C 34.486239,18.550987 34.149353,17.736936 33.931994,17.216882 L 33.536798,16.271332 L 34.139939,15.404381 C 34.47167,14.927561 34.938259,14.354621 35.176807,14.131184 C 35.579494,13.753999 35.672239,13.724934 36.473118,13.724934 C 37.271387,13.724934 37.390368,13.688009 38.068704,13.229752 C 38.47185,12.957405 38.970448,12.589869 39.176698,12.41301 L 39.551698,12.09145 L 38.051698,12.131596 C 36.887553,12.162751 36.45374,12.223687 36.114198,12.403749 C 35.243792,12.86533 33.659912,13.96415 33.235577,14.4008 C 32.996942,14.646361 32.767808,14.847871 32.726385,14.848602 C 32.684965,14.849335 32.307222,14.385639 31.886958,13.818166 C 31.466672,13.250662 30.884655,12.631956 30.593499,12.443166 C 30.124905,12.139326 29.948677,12.100581 29.057927,12.105571 C 28.504499,12.108672 27.903302,12.178985 27.721929,12.261821 C 27.361327,12.426516 25.7541,13.620652 25.744903,13.730711 C 25.741764,13.768262 26.25951,13.779016 26.895448,13.754606 C 27.891633,13.71637 28.107884,13.745566 28.457568,13.965511 C 28.85635,14.216339 30.168244,15.88905 30.694513,16.817694 L 30.962327,17.290276 L 29.589524,19.226352 C 28.834482,20.291197 27.856153,21.647025 27.415459,22.239302 C 26.974764,22.83158 26.614198,23.347952 26.614198,23.386796 C 26.614198,23.466289 27.945322,22.941525 28.614198,22.598344 L 28.614198,22.598342 z" id="path3943" style="fill:&fill_color;;fill-opacity:1"/>
+ <path d="M 7.8651415,13.479569 C 7.8656615,12.686394 7.921974,11.671809 7.9902803,11.224934 C 8.1084803,10.451649 8.8091515,8.7249335 9.0047365,8.7249335 C 9.2404628,8.7249335 11.364198,12.141534 11.364198,12.520762 C 11.364198,12.549399 11.20951,12.611599 11.020448,12.65898 C 10.472615,12.796272 9.3082628,13.556134 8.5567403,14.266805 L 7.8641978,14.9217 L 7.8651415,13.479569 z" id="path3945" style="fill:&fill_color;;fill-opacity:1"/>
+ </g>
+</svg>
diff --git a/activity/activity.info b/activity/activity.info
new file mode 100644
index 0000000..8ae84e0
--- /dev/null
+++ b/activity/activity.info
@@ -0,0 +1,6 @@
+[Activity]
+name = APRS
+activity_version= 1
+service_name = org.laptop.APRS
+icon = activity-aprs
+exec = sugar-activity aprs.APRSActivity
diff --git a/aprs.py b/aprs.py
new file mode 100755
index 0000000..0ec7ed5
--- /dev/null
+++ b/aprs.py
@@ -0,0 +1,928 @@
+# Copyright (C) 2008, Jack Zielke <jack@linuxcoffee.com>
+# Copyright (C) 2008, One Laptop Per Child
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import gtk
+import pango
+import time
+import socket
+import random
+import gobject
+
+from gettext import gettext as _
+
+from sugar import profile
+from sugar.activity import activity
+from sugar.bundle.activitybundle import ActivityBundle
+from sugar.graphics.toolbutton import ToolButton
+
+HOST = 'rotate.aprs2.net'
+#HOST = '192.168.50.6'
+PORT = 14580
+RECV_BUFFER = 4096
+
+bundle = ActivityBundle(activity.get_bundle_path())
+VERSION = bundle.get_activity_version()
+del bundle
+
+class APRSActivity(activity.Activity):
+ def __init__(self, handle):
+ activity.Activity.__init__(self, handle)
+ self.set_title(_('APRS Activity'))
+
+ self.connect('destroy', self.onDestroy)
+
+ self.sock = None
+ self.location = "home"
+ self.site = None
+ self.sent_acks = {}
+ self.timers = []
+ self.validating = False
+
+ titlefont = pango.FontDescription('Sans bold 8')
+ smallfont = pango.FontDescription('Sans 6')
+ verysmallfont = pango.FontDescription('Sans 3')
+ firstName = profile.get_nick_name().split(None, 1)[0].capitalize()
+
+ toolbox = activity.ActivityToolbox(self)
+ self.set_toolbox(toolbox)
+
+ activity_toolbar = toolbox.get_activity_toolbar()
+ activity_toolbar.share.props.visible = False
+ activity_toolbar.keep.props.visible = False
+
+ toolbox.show()
+
+ win = gtk.HBox(False, 10)
+ self.set_canvas(win)
+
+ leftwin = gtk.VBox(False, 10)
+
+ # Top 'about' box
+ aboutbox = gtk.VBox(False, 10)
+ aboutbox.set_border_width(10)
+
+ topaboutbox = gtk.VBox(False, 0)
+
+ titlebox = gtk.HBox(False, 0)
+ titlelabel = gtk.Label("APRS-XO:")
+ titlelabel.set_alignment(0, 0)
+ titlelabel.modify_font(titlefont)
+ titlebox.pack_start(titlelabel, False, False, 0)
+ titlelabel.show()
+ aboutlabel1 = gtk.Label("This amateur radio program will update your position")
+ aboutlabel1.set_alignment(0, 0.8)
+ titlebox.pack_start(aboutlabel1, False, False, 0)
+ aboutlabel1.show()
+ topaboutbox.pack_start(titlebox, False, False, 0)
+ titlebox.show()
+ aboutlabel2 = gtk.Label("& status on all of the global APRS web pages once every 10 minutes.")
+ aboutlabel2.set_alignment(0, 0)
+ topaboutbox.pack_start(aboutlabel2, False, False, 0)
+ aboutlabel2.show()
+ aboutbox.pack_start(topaboutbox, False, False, 0)
+ topaboutbox.show()
+
+ sitebox = gtk.HBox(False, 10)
+ sitelabel = gtk.Label("Select an APRS site:")
+ sitelabel.set_alignment(0, 0.4)
+ sitebox.pack_start(sitelabel, False, False, 0)
+ sitelabel.show()
+
+ findubutton = gtk.Button()
+ findubutton.set_label("FINDU.COM")
+ findubutton.connect("clicked", self.set_site, "http://www.findu.com/cgi-bin/symbol.cgi?icon=XA&limit=200")
+ sitebox.pack_start(findubutton, False, False, 0)
+ findubutton.show()
+
+ aprsworldbutton = gtk.Button()
+ aprsworldbutton.set_label("APRSworld")
+ aprsworldbutton.connect("clicked", self.set_site, "http://aprsworld.net/")
+ sitebox.pack_start(aprsworldbutton, False, False, 0)
+ aprsworldbutton.show()
+
+ otherbutton = gtk.Button()
+ otherbutton.set_label("About")
+ otherbutton.connect("clicked", self.set_site, "http://aprs.org/")
+ sitebox.pack_start(otherbutton, False, False, 0)
+ otherbutton.show()
+
+ aboutbox.pack_start(sitebox, False, False, 0)
+ sitebox.show()
+
+ infobox = gtk.VBox(False, 4)
+ # more info radio box?
+
+ infolabel = gtk.Label("Without a ham license you can only communicate with other XO's on the Internet.\nWith a ham license you can communicate worldwide with wireless and radio.")
+ infolabel.set_alignment(0, 0)
+ infolabel.modify_font(smallfont)
+ infobox.pack_start(infolabel, False, False, 0)
+ infolabel.show()
+
+ aboutbox.pack_start(infobox, False, False, 0)
+ infobox.show()
+
+ leftwin.pack_start(aboutbox, False, False, 0)
+ aboutbox.show()
+
+ separator = gtk.HSeparator()
+ leftwin.pack_start(separator, False, False, 0)
+ separator.show()
+
+ # identifiers box
+ identbox = gtk.HBox(False, 10)
+
+ leftidentbox = gtk.VBox(False, 10)
+ leftidentbox.set_border_width(10)
+ identlabel = gtk.Label("Identifiers")
+ identlabel.set_alignment(0, 0)
+ identlabel.modify_font(titlefont)
+ leftidentbox.pack_start(identlabel, False, False, 0)
+ identlabel.show()
+
+ spacerlabel = gtk.Label(" ")
+ spacerlabel.modify_font(verysmallfont)
+ leftidentbox.pack_start(spacerlabel, False, False, 0)
+ spacerlabel.show()
+
+ bottomleftidentbox = gtk.HBox(False, 0)
+
+ calllabel1 = gtk.Label("Callsign: ")
+ calllabel1.set_alignment(0, 0.2)
+ bottomleftidentbox.pack_start(calllabel1, False, False, 0)
+ calllabel1.show()
+
+ callbox = gtk.VBox(False, 4)
+ self.calltext = gtk.Entry()
+ self.calltext.set_max_length(9)
+ self.calltext.set_width_chars(6)
+ self.calltext.connect("changed", self.disable_beacon)
+ callbox.pack_start(self.calltext, False, False, 0)
+ self.calltext.show()
+
+ calllabel2 = gtk.Label("If a ham radio operator")
+ calllabel2.set_alignment(0, 0)
+ calllabel2.modify_font(smallfont)
+ callbox.pack_start(calllabel2, False, False, 0)
+ calllabel2.show()
+
+ bottomleftidentbox.pack_start(callbox, False, False, 0)
+ callbox.show()
+
+ leftidentbox.pack_start(bottomleftidentbox, False, False, 0)
+ bottomleftidentbox.show()
+
+ identbox.pack_start(leftidentbox, False, False, 0)
+ leftidentbox.show()
+
+ rightidentbox = gtk.VBox(False, 10)
+ rightidentbox.set_border_width(10)
+
+ toprightidentbox = gtk.HBox(False, 4)
+ namelabel = gtk.Label("First Name: ")
+ namelabel.set_alignment(0, 0.5)
+ toprightidentbox.pack_start(namelabel, False, False, 0)
+ namelabel.show()
+
+ self.nametext = gtk.Entry()
+ self.nametext.set_max_length(36)
+ self.nametext.set_width_chars(15)
+ self.nametext.set_text(firstName)
+ self.nametext.connect("changed", self.disable_beacon)
+ toprightidentbox.pack_start(self.nametext, False, False, 0)
+ self.nametext.show()
+ rightidentbox.pack_start(toprightidentbox, False, False, 0)
+ toprightidentbox.show()
+
+ bottomrightidentbox = gtk.HBox(False, 0)
+
+ ziplabel1 = gtk.Label("Zip Code: ")
+ ziplabel1.set_alignment(0, 0.5)
+ bottomrightidentbox.pack_start(ziplabel1, False, False, 0)
+ ziplabel1.show()
+
+ self.ziptext = gtk.Entry()
+ self.ziptext.set_max_length(5)
+ self.ziptext.set_width_chars(5)
+ bottomrightidentbox.pack_start(self.ziptext, False, False, 0)
+ self.ziptext.show()
+
+ rightidentbox.pack_start(bottomrightidentbox, False, False, 0)
+ bottomrightidentbox.show()
+
+ ziplabel2 = gtk.Label("otherwise your call will be XZZZZZ")
+ ziplabel2.set_alignment(0, 0)
+ ziplabel2.modify_font(smallfont)
+ rightidentbox.pack_start(ziplabel2, False, False, 0)
+ ziplabel2.show()
+
+ identbox.pack_start(rightidentbox, False, False, 0)
+ rightidentbox.show()
+
+ leftwin.pack_start(identbox, False, False, 0)
+ identbox.show()
+
+ separator = gtk.HSeparator()
+ leftwin.pack_start(separator, False, False, 0)
+ separator.show()
+
+ # station box
+ stationbox = gtk.VBox(False, 10)
+ stationbox.set_border_width(10)
+
+ topstationbox = gtk.HBox(False, 10)
+
+ stationlabel = gtk.Label("Station Text")
+ stationlabel.set_alignment(0, 0.5)
+ stationlabel.modify_font(titlefont)
+ topstationbox.pack_start(stationlabel, False, False, 0)
+ stationlabel.show()
+
+ self.stationtext = gtk.Entry()
+ self.stationtext.set_max_length(36)
+ self.stationtext.set_width_chars(36)
+ self.stationtext.connect("changed", self.disable_beacon)
+ topstationbox.pack_start(self.stationtext, False, False, 0)
+ self.stationtext.show()
+
+ stationbox.pack_start(topstationbox, False, False, 0)
+ topstationbox.show()
+
+ stationhelp = gtk.Label("Enter up to 36 characters, most important first since some displays\ncan only see the first 20 or 28.")
+ stationhelp.set_alignment(0, 0)
+ stationbox.pack_start(stationhelp, False, False, 0)
+ stationhelp.show()
+
+ leftwin.pack_start(stationbox, False, False, 0)
+ stationbox.show()
+
+ separator = gtk.HSeparator()
+ leftwin.pack_start(separator, False, False, 0)
+ separator.show()
+
+ # position box
+ positbox = gtk.VBox(False, 10)
+ positbox.set_border_width(10)
+
+ toppositbox = gtk.HBox(False, 30)
+
+ topleftpositbox = gtk.VBox(False, 4)
+
+ positlabel1 = gtk.Label("Position Data")
+ positlabel1.set_alignment(0, 0)
+ positlabel1.modify_font(titlefont)
+ topleftpositbox.pack_start(positlabel1, False, False, 0)
+ positlabel1.show()
+
+ latpositbox = gtk.HBox(False, 4)
+ latlabel1 = gtk.Label("Latitude: ")
+ latlabel1.set_alignment(0, 0.5)
+ latpositbox.pack_start(latlabel1, False, False, 0)
+ latlabel1.show()
+
+ self.latDDtext = gtk.Entry()
+ self.latDDtext.set_max_length(2)
+ self.latDDtext.set_width_chars(4)
+ self.latDDtext.set_text("DD")
+ self.latDDtext.select_region(1,2)
+ self.latDDtext.connect("changed", self.disable_beacon)
+ latpositbox.pack_start(self.latDDtext, False, False, 0)
+ self.latDDtext.show()
+
+ self.latMMtext = gtk.Entry()
+ self.latMMtext.set_max_length(2)
+ self.latMMtext.set_width_chars(3)
+ self.latMMtext.set_text("MM")
+ self.latMMtext.select_region(1,2)
+ self.latMMtext.connect("changed", self.disable_beacon)
+ latpositbox.pack_start(self.latMMtext, False, False, 0)
+ self.latMMtext.show()
+
+ latlabel2 = gtk.Label(".")
+ latlabel2.set_alignment(0, 1)
+ latpositbox.pack_start(latlabel2, False, False, 0)
+ latlabel2.show()
+
+ self.latmmtext = gtk.Entry()
+ self.latmmtext.set_max_length(2)
+ self.latmmtext.set_width_chars(3)
+ self.latmmtext.set_text("mm")
+ self.latmmtext.select_region(1,2)
+ self.latmmtext.connect("changed", self.disable_beacon)
+ latpositbox.pack_start(self.latmmtext, False, False, 0)
+ self.latmmtext.show()
+
+ self.latcombo = gtk.combo_box_new_text()
+ self.latcombo.append_text("N")
+ self.latcombo.append_text("S")
+ self.latcombo.set_active(0)
+ latpositbox.pack_start(self.latcombo, False, False, 0)
+ self.latcombo.show()
+
+ topleftpositbox.pack_start(latpositbox, False, False, 0)
+ latpositbox.show()
+
+ lonpositbox = gtk.HBox(False, 4)
+ lonlabel1 = gtk.Label("Longitude: ")
+ lonlabel1.set_alignment(0, 0.5)
+ lonpositbox.pack_start(lonlabel1, False, False, 0)
+ lonlabel1.show()
+
+ self.lonDDDtext = gtk.Entry()
+ self.lonDDDtext.set_max_length(3)
+ self.lonDDDtext.set_width_chars(4)
+ self.lonDDDtext.set_text("DDD")
+ self.lonDDDtext.select_region(1,2)
+ self.lonDDDtext.connect("changed", self.disable_beacon)
+ lonpositbox.pack_start(self.lonDDDtext, False, False, 0)
+ self.lonDDDtext.show()
+
+ self.lonMMtext = gtk.Entry()
+ self.lonMMtext.set_max_length(2)
+ self.lonMMtext.set_width_chars(3)
+ self.lonMMtext.set_text("MM")
+ self.lonMMtext.select_region(1,2)
+ self.lonMMtext.connect("changed", self.disable_beacon)
+ lonpositbox.pack_start(self.lonMMtext, False, False, 0)
+ self.lonMMtext.show()
+
+ lonlabel2 = gtk.Label(".")
+ lonlabel2.set_alignment(0, 1)
+ lonpositbox.pack_start(lonlabel2, False, False, 0)
+ lonlabel2.show()
+
+ self.lonmmtext = gtk.Entry()
+ self.lonmmtext.set_max_length(2)
+ self.lonmmtext.set_width_chars(3)
+ self.lonmmtext.set_text("mm")
+ self.lonmmtext.select_region(1,2)
+ self.lonmmtext.connect("changed", self.disable_beacon)
+ lonpositbox.pack_start(self.lonmmtext, False, False, 0)
+ self.lonmmtext.show()
+
+ self.loncombo = gtk.combo_box_new_text()
+ self.loncombo.append_text("W")
+ self.loncombo.append_text("E")
+ self.loncombo.set_active(0)
+ lonpositbox.pack_start(self.loncombo, False, False, 0)
+ self.loncombo.show()
+
+ topleftpositbox.pack_start(lonpositbox, False, False, 0)
+ lonpositbox.show()
+
+ toppositbox.pack_start(topleftpositbox, False, False, 0)
+ topleftpositbox.show()
+
+ toprightpositbox = gtk.VBox(False, 4)
+
+ loclabel = gtk.Label("Location Type:")
+ loclabel.set_alignment(0, 0)
+ toprightpositbox.pack_start(loclabel, False, False, 0)
+ loclabel.show()
+
+ locbox = gtk.HBox(False, 4)
+
+ leftlocbox = gtk.VBox(False, 4)
+
+ locbutton = gtk.RadioButton(None, "home")
+ locbutton.connect("toggled", self.set_location, "home")
+ locbutton.set_active(True)
+ leftlocbox.pack_start(locbutton, False, False, 0)
+ locbutton.show()
+
+ locbutton = gtk.RadioButton(locbutton, "work")
+ locbutton.connect("toggled", self.set_location, "work")
+ leftlocbox.pack_start(locbutton, False, False, 0)
+ locbutton.show()
+
+ locbutton = gtk.RadioButton(locbutton, "school")
+ locbutton.connect("toggled", self.set_location, "school")
+ leftlocbox.pack_start(locbutton, False, False, 0)
+ locbutton.show()
+
+ locbox.pack_start(leftlocbox, False, False, 0)
+ leftlocbox.show()
+
+ rightlocbox = gtk.VBox(False, 4)
+
+ locbutton = gtk.RadioButton(locbutton, "club")
+ locbutton.connect("toggled", self.set_location, "club")
+ rightlocbox.pack_start(locbutton, False, False, 0)
+ locbutton.show()
+
+ locbutton = gtk.RadioButton(locbutton, "visiting")
+ locbutton.connect("toggled", self.set_location, "visiting")
+ rightlocbox.pack_start(locbutton, False, False, 0)
+ locbutton.show()
+
+ locbutton = gtk.RadioButton(locbutton, "other")
+ locbutton.connect("toggled", self.set_location, "other")
+ rightlocbox.pack_start(locbutton, False, False, 0)
+ locbutton.show()
+
+ locbox.pack_start(rightlocbox, False, False, 0)
+ rightlocbox.show()
+
+ toprightpositbox.pack_start(locbox, False, False, 0)
+ locbox.show()
+
+ toppositbox.pack_start(toprightpositbox, False, False, 0)
+ toprightpositbox.show()
+
+ positbox.pack_start(toppositbox, False, False, 0)
+ toppositbox.show()
+
+ positlabel2 = gtk.Label("If you do not know your LAT/LONG then your\nzip code will be used to place you on the map.")
+ positlabel2.set_alignment(0, 0)
+ positbox.pack_start(positlabel2, False, False, 0)
+ positlabel2.show()
+
+ leftwin.pack_start(positbox, False, False, 0)
+ positbox.show()
+
+ separator = gtk.HSeparator()
+ leftwin.pack_start(separator, False, False, 0)
+ separator.show()
+
+ # defined here so clear and connect buttons have access
+ statusview = gtk.TextView()
+ self.statusbuffer = statusview.get_buffer()
+
+ connectbutton = gtk.Button()
+ connectbutton.set_label("Connect")
+ connectbutton.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#00b20d"))
+ connectbutton.connect("clicked", self.connect_aprs)
+ leftwin.pack_start(connectbutton, False, False, 12)
+ connectbutton.show()
+
+ win.pack_start(leftwin, False, False, 0)
+ leftwin.show()
+
+ rightwin = gtk.VBox(False, 4)
+
+ rightwintopbox = gtk.HBox(False, 4)
+
+ clearbutton = gtk.Button()
+ clearbutton.set_label(" Clear ")
+ clearbutton.connect("clicked", self.clear_status)
+ rightwintopbox.pack_start(clearbutton, False, False, 20)
+ clearbutton.show()
+
+ self.beaconbutton = gtk.CheckButton("Beacon every 10 minutes")
+ self.beaconbutton.set_active(True)
+ self.beaconbutton.connect("toggled", self.enable_beacon, "beacon")
+ rightwintopbox.pack_start(self.beaconbutton, False, False, 20)
+ self.beaconbutton.show()
+
+ rightwin.pack_start(rightwintopbox, False, False, 0)
+ rightwintopbox.show()
+
+ statusview.set_editable(False)
+ statusview.set_cursor_visible(True)
+ statusview.set_wrap_mode(gtk.WRAP_CHAR)
+ statusview.set_justification(gtk.JUSTIFY_LEFT)
+ statusview.modify_font(smallfont)
+
+ self.statusbuffer.set_text("Welcome to APRS-XO.\n\nThis program sends your position information to a\nserver that will then display your location on\na webpage. This program requires an active\nInternet connection to work.\n\nSelect an APRS Site\nSelecting a button will copy the URI to the\nclipboard.\n\nIndentifiers\nIf you are not a ham radio operator enter your\nfirst name and zip code.\n\nIf you are a ham radio operator enter your first\nname, call sign, and position data. If position\nis unknown, leave the call sign field blank and\nenter your 5 digit zip code.\n\nStation Text\nData in the Station Text field will appear\nafter your location information on the website.\n\nBeacon\nWhen selected, sends location data every 10\nminutes. The beacon will automatically stop\nwhen you edit personal information. Must be\nmanually reselected after edit completion.\n\nAPRS Copyright (c) Bob Bruninga WB4APR\n\n")
+
+ self.statuswindow = gtk.ScrolledWindow()
+ self.statuswindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
+ self.statuswindow.add_with_viewport(statusview)
+ statusview.show()
+ rightwin.pack_start(self.statuswindow, True, True, 0)
+ self.statuswindow.show()
+
+ # when messaging is enabled, put a textview for messages above the status textview
+ # move the messagebox between them.
+ messagebox = gtk.HBox(False, 4)
+
+ self.messagecombo = gtk.combo_box_entry_new_text()
+ self.messagecombo.append_text("ALL")
+ self.messagecombo.append_text("BEACON")
+ self.messagecombo.append_text("CQ")
+ self.messagecombo.append_text("QST")
+ self.messagecombo.set_active(-1)
+ self.messagedest = self.messagecombo.get_child()
+ self.messagedest.set_max_length(9)
+ self.messagedest.set_width_chars(5)
+ self.messagedest.modify_font(smallfont)
+ messagebox.pack_start(self.messagecombo, False, False, 0)
+ self.messagecombo.show()
+
+ self.messagetext = gtk.Entry()
+ self.messagetext.set_max_length(67)
+ self.messagetext.set_width_chars(23)
+ self.messagetext.modify_font(smallfont)
+ self.messagetext.connect("activate", self.send_message, self.messagetext)
+ messagebox.pack_start(self.messagetext, False, False, 0)
+ self.messagetext.show()
+
+ messagebutton = gtk.Button()
+ messagebutton.set_label("Send")
+ messagebutton.connect("clicked", self.send_message, "message")
+ messagebox.pack_start(messagebutton, False, False, 0)
+ messagebutton.show()
+
+ rightwin.pack_start(messagebox, False, False, 0)
+ messagebox.show()
+
+ self.rawbox = gtk.HBox(False, 6)
+
+ self.rawtext = gtk.Entry()
+ self.rawtext.set_max_length(128)
+ self.rawtext.set_width_chars(34)
+ self.rawtext.modify_font(smallfont)
+ self.rawtext.connect("activate", self.raw_send)
+ self.rawbox.pack_start(self.rawtext, False, False, 0)
+ self.rawtext.show()
+
+ rawbutton = gtk.Button()
+ rawbutton.set_label("Send")
+ rawbutton.connect("clicked", self.raw_send)
+ self.rawbox.pack_start(rawbutton, False, False, 0)
+ rawbutton.show()
+
+ rightwin.pack_start(self.rawbox, False, False, 0)
+ # only show if aprsd says you are verified
+ #rawbox.show()
+
+ win.pack_start(rightwin, False, False, 0)
+ rightwin.show()
+
+ win.show()
+
+ def clear_status(self, button):
+ self.statusbuffer.delete(self.statusbuffer.get_start_iter(), self.statusbuffer.get_end_iter())
+
+ def connect_aprs(self, button):
+ if (self.validate_data() == False):
+ return False
+ if (self.sock == None):
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.status_write("Connecting ")
+ iplist = socket.gethostbyname_ex(HOST)[2]
+ server = random.choice(iplist)
+ self.status_write("to %s\n" % server)
+ try:
+ self.sock.connect((server, PORT))
+ except socket.error, msg:
+ self.status_write(msg[1])
+ self.sock = None
+ return
+
+ self.status_write("Connected\n")
+ button.set_label("Disconnect")
+ button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#e6000a"))
+
+ response = self.sock.recv(RECV_BUFFER)
+ self.status_write("%s" % response)
+ if (response.find("javAPRSSrvr") == -1):
+ self.status_write("invalid response.")
+ self.disconnect_aprs(button)
+
+ # hidden feature
+ # if you have callsign, zip code and position - send zip as password
+ if (self.calltext.get_text() != "" and self.ziptext.get_text() != "" and self.latDDtext.get_text() != "DD"):
+ sendme = "user %s pass %s vers aprs_xo %d\n" % (self.calltext.get_text(), self.ziptext.get_text(), VERSION)
+ else:
+ sendme = "user %s vers aprs_xo %d\n" % (self.calltext.get_text(), VERSION)
+ self.sock.sendall(sendme)
+ self.status_write("%s" % sendme)
+
+ response = self.sock.recv(RECV_BUFFER)
+ self.status_write("%s" % response)
+ if (response.find("# logresp") == -1):
+ self.status_write("invalid response.")
+ self.disconnect_aprs(button)
+ if (response.find("unverified") == -1):
+ self.rawbox.show()
+
+ self.input_watch = gobject.io_add_watch(self.sock, gobject.IO_IN, self.recv_data)
+
+ # send banner
+ sendme = "%s>APRS-XO v%s\n" % (self.calltext.get_text(), VERSION)
+ self.sock.sendall(sendme)
+
+ self.send_beacon()
+ self.output_watch = gobject.timeout_add(10 * 60 * 1000, self.send_beacon)
+ else:
+ self.disconnect_aprs(button)
+ gobject.source_remove(self.input_watch)
+ gobject.source_remove(self.output_watch)
+
+ def disconnect(self):
+ # for test server only
+ if(HOST == "192.168.50.6"):
+ self.sock.sendall("q")
+
+ self.sock.close()
+ self.sock = None
+
+ def disconnect_aprs(self, button):
+ self.disconnect()
+
+ self.status_write("Disconnected\n")
+ button.set_label("Connect")
+ button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#00b20d"))
+ self.rawbox.hide()
+
+ def recv_data(self, sock, condition):
+ while 1:
+ try:
+ recv_data = sock.recv(RECV_BUFFER)
+ except:
+ self.status_write("Server closed connection.\n")
+ return False
+ if not recv_data:
+ self.status_write("Server closed connection.\n")
+ return False
+ else:
+ self.status_write(recv_data)
+ self.msg_check(recv_data)
+ return True
+
+ def send_beacon(self):
+ if (self.beaconbutton.get_active()):
+ beacon = "%s>APOLPC:=%s%s.%s%sX%s%s.%s%sA%s's XO at %s. %s\n" % (self.calltext.get_text(), self.latDDtext.get_text(), self.latMMtext.get_text(), self.latmmtext.get_text(), self.latcombo.get_active_text(), self.lonDDDtext.get_text(), self.lonMMtext.get_text(), self.lonmmtext.get_text(), self.loncombo.get_active_text(), self.nametext.get_text(), self.location, self.stationtext.get_text())
+ try:
+ self.sock.sendall(beacon)
+ except:
+ self.status_write("\nProblem sending beacon - STOPPED")
+ return False
+ self.status_write("%s" % beacon)
+ return True
+ else:
+ return True
+
+ def send_data(self, msg):
+ text = "%s>APOLPC:%s\n" % (self.calltext.get_text(), msg)
+ try:
+ self.sock.sendall(text)
+ except:
+ self.status_write("Problem sending message\n")
+ self.sock = None
+ return False
+ self.status_write("%s" % text)
+ return True
+
+ def send_ack(self, msg):
+ self.send_data(msg)
+ return False
+
+ def status_write(self, text):
+ self.statusbuffer.insert(self.statusbuffer.get_end_iter(), text)
+ adjustment = self.statuswindow.get_vadjustment()
+ adjustment.set_value(adjustment.upper)
+
+ def set_location(self, widget, data=None):
+ self.location = data
+
+ def set_site(self, widget, data=None):
+ self.site = data
+ self.clipboard()
+
+ def validate_data(self):
+ stop_here = False
+ self.validating = True
+ beaconchecked = self.beaconbutton.get_active()
+
+ if (self.nametext.get_text() == ""):
+ self.status_write("First Name is required\n")
+ stop_here = True
+
+ if (self.calltext.get_text() == "" and self.ziptext.get_text() == ""):
+ self.status_write("A callsign or zip code must be provided.\n")
+ self.validating = False
+ return False
+
+ if (stop_here):
+ self.validating = False
+ return False
+
+ # convert zip to position
+ if (self.calltext.get_text() == "" and self.ziptext.get_text() != "" and self.latDDtext.get_text() == "DD"):
+ self.status_write("Attempting to set location from zip code\n")
+ self.ziptext.set_text(self.ziptext.get_text().zfill(5))
+ try:
+ zipsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ except socket.error, msg:
+ self.status_write("[ERROR] %s\n" % msg[1])
+ self.validating = False
+ return False
+ try:
+ zipsock.connect(('geocoder.us', 80))
+ except socket.error, msg:
+ self.status_write("[ERROR] %s\n" % msg[1])
+ self.validating = False
+ return False
+ try:
+ zipsock.sendall("GET /service/csv/geocode?zip=%s\n" % self.ziptext.get_text())
+ except socket.error, msg:
+ self.status_write("[ERROR] %s\n" % msg[1])
+ self.validating = False
+ return False
+ zipsock.shutdown(1)
+ try:
+ response = zipsock.recv(RECV_BUFFER)
+ except socket.error, msg:
+ self.status_write("[ERROR] %s\n" % msg[1])
+ self.validating = False
+ return False
+ A = random.randrange(0,9)
+ O = random.randrange(0,9)
+ self.calltext.set_text("X%s-%d%d" % (self.ziptext.get_text(), A, O))
+ try:
+ (lat, lon, junk) = response.split(',', 2)
+ except:
+ self.status_write("%s\n" % response)
+ lat = "0"
+ lon = "0"
+ lat = float(lat.strip())
+ lon = float(lon.strip())
+ if (lat < 0):
+ self.latcombo.set_active(1) # S
+ else:
+ self.latcombo.set_active(0) # N
+ lat = abs(lat)
+ if (lon < 0):
+ self.loncombo.set_active(0) # W
+ else:
+ self.loncombo.set_active(1) # E
+ lon = abs(lon)
+ self.latDDtext.set_text("%02d" % int(lat))
+ self.latMMtext.set_text("%02d" % int((lat - int(lat)) * 60 + 0.5))
+ self.latmmtext.set_text("%d " % A)
+ self.lonDDDtext.set_text("%03d" % int(lon))
+ self.lonMMtext.set_text("%02d" % int((lon - int(lon)) * 60 + 0.5))
+ self.lonmmtext.set_text("%d " % O)
+ self.ziptext.set_text("")
+ # end set loc by zip code
+
+ if (self.latDDtext.get_text() == "DD" or self.latDDtext.get_text() == ""):
+ self.status_write("Latitude Degrees are required.\n")
+ stop_here = True
+ if (self.latMMtext.get_text() == "MM" or self.latMMtext.get_text() == ""):
+ self.status_write("Latitude Minutes are required.\n")
+ stop_here = True
+ if (self.lonDDDtext.get_text() == "DDD" or self.lonDDDtext.get_text() == ""):
+ self.status_write("Longitude Degrees are required.\n")
+ stop_here = True
+ if (self.lonMMtext.get_text() == "MM" or self.lonMMtext.get_text() == ""):
+ self.status_write("Longitude Minutes are required.\n")
+ stop_here = True
+
+ if (stop_here):
+ self.status_write("Latitude and Longitude must be complete.\nFor position ambiguity omit decimal Minutes (mm).\nIf you do not know your lat/lon, leave the letters\n(DD, MM, etc) and provide your zip code.\n")
+ self.validating = False
+ return False
+
+ if (not self.latDDtext.get_text().isdigit()):
+ self.status_write("Latitude Degrees must be a number.\n")
+ stop_here = True
+ if (not self.latMMtext.get_text().isdigit()):
+ self.status_write("Latitude Minutes must be a number.\n")
+ stop_here = True
+ if (not self.lonDDDtext.get_text().isdigit()):
+ self.status_write("Longitude Degrees must be a number.\n")
+ stop_here = True
+ if (not self.lonMMtext.get_text().isdigit()):
+ self.status_write("Longitude Minutes must be a number.\n")
+ stop_here = True
+
+ if (stop_here):
+ self.status_write("Invalid Position.\n")
+ self.validating = False
+ return False
+
+ if (int(self.latDDtext.get_text()) < 0 or int(self.latDDtext.get_text()) > 90):
+ self.status_write("Latitude Degrees must be between 0 and 90.\n")
+ stop_here = True
+ if (int(self.latMMtext.get_text()) < 0 or int(self.latMMtext.get_text()) > 60):
+ self.status_write("Latitude Minutes must be between 0 and 60.\n")
+ stop_here = True
+ if (int(self.lonDDDtext.get_text()) < 0 or int(self.lonDDDtext.get_text()) > 180):
+ self.status_write("Longitude Degrees must be between 0 and 180.\n")
+ stop_here = True
+ if (int(self.lonMMtext.get_text()) < 0 or int(self.lonMMtext.get_text()) > 60):
+ self.status_write("Longitude Minutes must be between 0 and 60.\n")
+ stop_here = True
+
+ if (stop_here):
+ self.status_write("Invalid Position.\n")
+ self.validating = False
+ return False
+
+ # clean up entries
+ self.latDDtext.set_text(self.latDDtext.get_text().zfill(2))
+ self.latMMtext.set_text(self.latMMtext.get_text().zfill(2))
+ self.lonDDDtext.set_text(self.lonDDDtext.get_text().zfill(3))
+ self.lonMMtext.set_text(self.lonMMtext.get_text().zfill(2))
+ self.latmmtext.set_text(self.latmmtext.get_text().ljust(2))
+ self.lonmmtext.set_text(self.lonmmtext.get_text().ljust(2))
+ if (self.latmmtext.get_text() == "mm"):
+ self.latmmtext.set_text(" ")
+ if (self.lonmmtext.get_text() == "mm"):
+ self.lonmmtext.set_text(" ")
+ self.calltext.set_text(self.calltext.get_text().upper())
+ self.beaconbutton.set_active(beaconchecked)
+ self.validating = False
+
+ def onDestroy(self, junk=None ):
+ if (self.sock != None):
+ self.disconnect()
+
+# def write_file(self, filename):
+# # does not appear to run so commented out for now
+# self.metadata['callsign'] = self.calltext.get_text()
+# self.metadata['latDD'] = self.latDDtext.get_text()
+# self.metadata['latMM'] = self.latMMtext.get_text()
+# self.metadata['latmm'] = self.latmmtext.get_text()
+# self.metadata['lat'] = self.latcombo.get_active()
+# self.metadata['lonDDD'] = self.lonDDDtext.get_text()
+# self.metadata['lonMM'] = self.lonMMtext.get_text()
+# self.metadata['lonmm'] = self.lonmmtext.get_text()
+# self.metadata['lon'] = self.loncombo.get_active()
+# self.metadata['nick_name'] = self.nametext.get_text()
+# self.metadata['location'] = self.location
+# self.metadata['stationtext'] = self.stationtext.get_text()
+# self.metadata['site'] = self.site
+# self.metadata['zip'] = self.ziptext.get_text()
+# self.metadata['beacon'] = self.beaconbutton.get_active()
+# # should save list of callsigns used in outgoing messages
+
+# def read_file(self, filename):
+# # does not appear to run so commented out for now
+# self.calltext.set_text(self.metadata.get('callsign', ""))
+
+ def msg_check(self, data):
+ # a quick "does it look like a message?" check
+ firstcheck = data.find("::")
+ secondcheck = data.find("{")
+ if (firstcheck != -1 and secondcheck != -1):
+ # great, it looks kinda like a message, is it to me?
+ tocall = data[firstcheck+2:firstcheck+11]
+ if (tocall.strip().upper() == self.calltext.get_text()):
+ sequence_end = data.find("}")
+ if (sequence_end == -1):
+ sequence = data[secondcheck+1:-1]
+ else:
+ sequence = data[secondcheck+1:sequence_end]
+ fromcall = data[:data.find(">")]
+ message = ":%s:ack%s" % (fromcall, sequence)
+ self.send_data(message)
+ id = "%s-%s" % (fromcall, sequence)
+ if (id in self.sent_acks):
+ self.timers.append(gobject.timeout_add(30 * 1000, self.send_ack, message))
+ self.timers.append(gobject.timeout_add(60 * 1000, self.send_ack, message))
+ self.timers.append(gobject.timeout_add(120 * 1000, self.send_ack, message))
+
+ self.sent_acks[id] = time.time() # to help a cleanup thread later
+ self.sent_acks[fromcall] = sequence # to help with reply acks later
+
+ def disable_beacon(self, widget, data=None):
+ if (self.sock != None):
+ self.beaconbutton.set_active(False)
+
+ def enable_beacon(self, widget, data=None):
+ if (not self.validating and widget.get_active()):
+ self.validate_data()
+
+ def raw_send(self, widget, data=None):
+ msg = "%s\n" % self.rawtext.get_text()
+ try:
+ self.sock.sendall(msg)
+ except:
+ self.status_write("Problem sending message\n")
+ self.sock = None
+ return False
+ self.status_write(msg)
+ self.rawtext.set_text("")
+ return True
+
+ def send_message(self, widget, data=None):
+ self.status_write("This version of APRS-XO can not send messages.\n")
+ self.messagetext.set_text("")
+
+ def clipboard(self):
+ clipboard = gtk.clipboard_get()
+ target = [("text/uri-list", 0, 0)]
+ clipboard.set_with_data(target, self.clipboard_get, self.clipboard_clear, (self.site))
+
+ def clipboard_get(self, clipboard, selection, info, data):
+ selection.set_uris([data])
+
+ def clipboard_clear(self, clipboard, data):
+ pass
diff --git a/locale/en/LC_MESSAGES/org.laptop.APRS.mo b/locale/en/LC_MESSAGES/org.laptop.APRS.mo
new file mode 100644
index 0000000..e17477a
--- /dev/null
+++ b/locale/en/LC_MESSAGES/org.laptop.APRS.mo
Binary files differ
diff --git a/locale/en/activity.linfo b/locale/en/activity.linfo
new file mode 100644
index 0000000..9c05e71
--- /dev/null
+++ b/locale/en/activity.linfo
@@ -0,0 +1,2 @@
+[Activity]
+name = APRS
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..93b4ce8
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,3 @@
+#!/usr/bin/env python
+from sugar.activity import bundlebuilder
+bundlebuilder.start("APRS")