tvdb update

git-svn-id: file:///root/webif/svn/pkg/webif/trunk@2534 2a923420-c742-0410-a762-8d5b09965624
This commit is contained in:
hummypkg 2015-11-06 18:50:27 +00:00
parent b373ccb3dc
commit f34872a4c4
19 changed files with 214 additions and 8965 deletions

View File

@ -1,7 +1,7 @@
Package: webif
Priority: optional
Section: web
Version: 1.2.5-5
Version: 1.2.5-6
Architecture: mipsel
Maintainer: af123@hummypkg.org.uk
Depends: webif-channelicons(>=1.1.18),lighttpd(>=1.4.35-2),jim(>=0.76),jim-oo,jim-sqlite3(>=0.76),jim-cgi(>=0.7),jim-binary(>=0.76),service-control(>=2.1),busybox(>=1.20.2-1),lsof(>=4.87),epg(>=1.2.0),hmt(>=2.0.7),ssmtp,anacron,trm(>=1.1),openssl-command,nicesplice,id3v2,file,rsvsync(>=1.0.2),webif-charts(>=1.2-1),stripts(>=1.2.5-3),smartmontools,tmenu(>=1.08),ffmpeg,id3v2,multienv(>=1.6),tcpping(>=1.1),e2fsprogs,wireless-tools(>=29-1),dbupdate,recmon(>=2.0.7)

View File

@ -18,6 +18,12 @@ if {$type eq "ts"} {
set ts [ts fetch $file]
# Causes other series information to be automatically populated
set epname [$ts episode_name]
set series [$ts series_name]
set sdata [$ts get tvdb_series]
set idata [$ts get tvdb_data]
puts "
<table class=keyval>
<tr>
@ -25,7 +31,15 @@ if {$type eq "ts"} {
<td class=va>
"
if {[file exists "[file rootname $file].thm"]} {
puts "<img class=\"bmp va\" width=70 height=39 src=\"bmp.jim?file=$file\">"
puts "<img class=\"bmp va\" src=\"bmp.jim?file=$file\">"
}
if {[dict exists $idata thumb]} {
puts "
<img class=\"rollimg va\"
src=\"[tvdb bannerurl $idata(thumb)]\">
<div id=rollimg class=hidden></div>
"
}
puts "[$ts get title]</td>
</tr><tr>
@ -34,11 +48,6 @@ if {$type eq "ts"} {
</tr><tr>
<th>Episode</th>
"
# Causes other series information to be automatically populated
set epname [$ts episode_name]
set series [$ts series_name]
set sdata [$ts get tvdb_series]
set idata [$ts get tvdb_data]
if {[llength $sdata]} {
set sid [$sdata get seriesid]
if {$sid} {
@ -51,22 +60,30 @@ if {$type eq "ts"} {
</tr><tr>
"
if {[llength $sdata] && [llength $idata]} {
puts "</tr><tr><th class=blood>TVDB</th><td class=footnote>
<img class=collapser id=xtvdb x=tvdb_extra class=va
src=/img/tree/plusonly.png>
Found using [$ts get tvdb_method]
puts "</tr><tr><th>TheTVDB</th><td>
<img class=collapser id=xtvdb x=tvdb_extra
class=va src=/img/tree/plusonly.png>
Found episode using [$ts get tvdb_method]
<div id=tvdb_extra class=hidden>
$idata(overview)
<div class=blood>
$idata(overview)
</div>
"
if {[[settings] tvdb_debug]} {
puts "
<div class=bluefootnote>
[$sdata get _phrases]
</div>
<div class=footnote>
[lrange [$sdata get _smatches] 0 8]
</div>
"
}
puts "
</div>
</td></tr>"
}
# $idata(overview)
# <br>
# [$sdata get _phrases]
# <br>
# [lrange [$sdata get _smatches] 0 8]
if {[$ts flag "Guidance"] > 0} {
puts "
<th>Guidance</th>
@ -179,7 +196,9 @@ if {[$ts get bookmarks]} {
"
}
puts "</table>"
puts "
</table>
"
puts {
<script type=text/javascript>
$('.collapser').on('click', function() {
@ -193,6 +212,22 @@ $('.collapser').on('click', function() {
});
});
$('img.rollimg').hover(
function() {
var img = this, $img = $(img), offset = $img.offset;
$('#rollimg').css({
top: offset.top,
left: offset.left
})
.append($img.clone().removeClass('rollimg'))
.removeClass('hidden');
},
function() {
$('#rollimg').empty().addClass('hidden');
}
);
</script>
}
exit

View File

@ -22,11 +22,11 @@ puts {
<div id=tvdbresults title="Choose Series" class=hidden>
<div class=tvdbresults id=tvdbresults_loading>
<img src=/img/loading.gif>
Searching theTVDB.com database, please wait...
Searching TheTVDB.com database, please wait...
</div>
<div class=tvdbresults id=tvdbresults_saving>
<img src=/img/loading.gif>
Retrieving episode details from theTVDB.com, please wait...
Retrieving episode details from TheTVDB.com, please wait...
</div>
<div class=tvdbresults id=tvdbresults_force>
You can optionally force a particular series number for this folder.<br>
@ -42,11 +42,6 @@ puts {
<td>
<input id=tvdb_forceseries type=number value="" min=0>
</td>
</tr><tr>
<td></td>
<td>
<button id=tvdbresults_forcesave>Save</button>
</td>
</tr>
</table>
</div>

View File

@ -18,9 +18,9 @@ function select_episode()
$('.tvdbresults').hide();
$('#tvdbresults_force').show();
$('#tvdb_forceseries').attr('max', data).val(0);
$('#tvdbresults_forcesave')
.button()
.on('click', function() {
$('#tvdbresults').dialog('option', 'buttons', {
"Save": function() {
$('.tvdbresults').hide();
$('#tvdbresults_saving').show();
$('#tvdbresults').diagrefresh();
@ -31,7 +31,8 @@ function select_episode()
}, function() {
window.location.reload(true);
});
});
}
});
});
}

View File

@ -9,7 +9,9 @@ if {$term eq "-"} exit
httpheader
foreach series [[tvdb] searchseries $term] {
set slist [[tvdb] searchseries $term]
if {[llength $slist]} {
foreach series $slist {
puts "
<div>
<div class=tvdbseries>
@ -24,9 +26,16 @@ foreach series [[tvdb] searchseries $term] {
</button>
</div>
<div class=tvdbsynopsis>
$series(overview)
"
if {[dict exists $series overview]} {
puts $series(overview)
}
puts "
</div>
</div>
"
}
} else {
puts "No matches found."
}

View File

@ -260,7 +260,7 @@ pre, .pre
background: transparent;
}
.footnote, .bfootnote
.footnote, .bfootnote, .bluefootnote
{
background: transparent;
font-size: 70%;
@ -272,6 +272,11 @@ pre, .pre
color: #ff4000 !important;
}
.bluefootnote
{
color: #0000ff !important;
}
tr.blueshade > td, .blueshade
{
background: #b9daff !important;
@ -569,3 +574,14 @@ span.foldernum
z-index: 40;
}
#rollimg
{
position: absolute;
}
img.rollimg
{
height: 78px;
width: 140px;
}

View File

@ -26,7 +26,8 @@ proc dedupprocess {file} {{seen {}}} {
set epname [$ts episode_name]
if {[$ts get tvdb_method] ne "" && [$ts get episodenum] > 0} {
set syn "[$ts epstr] - $epname"
set syn [$ts epstr [[settings] dedup_template]]
append syn $epname
} else {
set syn $epname
}

View File

@ -156,12 +156,6 @@ puts {
</tr>
</table>
<span class=also style="padding-left: 5px">
View:
<a href=/jim/ref.html target=_blank>Jim Reference Manual</a> |
<a href=/jim/oo.html target=_blank>OO</a> |
<a href=/jim/sqlite.html target=_blank>Sqlite</a>
</span>
</fieldset>
<fieldset class=left>

BIN
webif/html/img/tvdb-sm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 B

View File

@ -1,372 +0,0 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Jim Tcl - Object Oriented</title>
<link rel="stylesheet" type="text/css" href="/css/style.css" media="screen">
<link rel="stylesheet" type="text/css" href="/css/sh_style.css" media="screen">
<script src="/javascript/sh_main.min.js" type="text/javascript"></script>
<script src="/javascript/sh_lang.js" type="text/javascript"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-23178588-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<meta name="generator" content="nanoc 3.1.6">
</head>
<body>
<div id="header">
<h1 id="blog-title">The Jim Interpreter</h1>
<p id="description">A small footprint implementation of the Tcl programming language</p>
</div>
<div id="content">
<div class="breadcrumbs">
<a href="/">The Jim Interpreter</a>
»
<a href="/documentation/">Documentation</a>
»
<a href="/documentation/oo/">Object Oriented</a>
</div>
<div class="main" id="main">
<h1 id="object-oriented-support-for-jim-tcl">Object Oriented Support for Jim Tcl</h1>
<h2 id="overview">OVERVIEW</h2>
<p>The pure-Tcl oo package leverages Jim&rsquo;s unique strengths
to provide support for Object Oriented programming. </p>
<p>The oo package can be statically linked with Jim or installed
as a separate Tcl package and loaded with:</p>
<pre class="sh_tcl">
package require oo
</pre>
<h2 id="declaring-classes">DECLARING CLASSES</h2>
<p>A class is declared with the <code>class</code> proc as follows.</p>
<pre class="sh_tcl">
class myclass ?baseclasses? classvars
</pre>
<p>This declares a class named <code>myclass</code> with the given dictionary,
<code>classvars</code>, providing the initial state of all new objects.
It is important to list all class variables in <code>classvars</code>, even
if initialised only to the empty string, since the class makes
these variables available in methods and via <code>[myclass vars]</code>.</p>
<p>A list of zero or more base classes may also be specified from
which methods and class variables are imported. See INHERITANCE
below for more details.</p>
<p>Declaring a class creates a procedure with the class name along
with some related procedures. For example:</p>
<pre class="sh_tcl">
. class Account {balance 0}
Account
. info procs Account*
{Account get} {Account methods} {Account eval} Account {Account new} {Account destroy}
{Account vars} {Account classname} {Account classvars} {Account method}
</pre>
<p>Notice that apart from the main <code>Account</code> procedure, all the remaining procedures (methods)
are prefixed with <code>Account</code> and a space.</p>
<h2 id="predefined-class-methods">PREDEFINED CLASS METHODS</h2>
<p>Decaring a class pre-defines a number of &ldquo;class&rdquo; methods. i.e. those which don&rsquo;t
require an object and simply return or manipulate properties of the class. These are:</p>
<dl>
<dt><strong>new</strong> ?instancevars?</dt>
<dd>Creates and returns new object, optionally overriding the default class variable values.
Note that the class name is an alias for <code>classname new {}</code> and can be used as a shorthand
for creating new objects with default values.</dd>
</dl>
<dl>
<dt><strong>method</strong> name arglist body</dt>
<dd>Creates or redefines a method for the class with the given name, argument list and body.</dd>
</dl>
<dl>
<dt><strong>methods</strong></dt>
<dd>Returns a list of the methods supported by this class, including both class methods
and instance methods. Also includes base class methods.</dd>
</dl>
<dl>
<dt><strong>vars</strong></dt>
<dd>Returns a list of the class variables for this class (names
only). Also includes base class variables.</dd>
</dl>
<dl>
<dt><strong>classvars</strong></dt>
<dd>Returns a dictionary the class variables, including initial values, for this class.
Also includes base class variables.</dd>
</dl>
<dl>
<dt><strong>classname</strong></dt>
<dd>Returns the classname. This can be useful as [$self classname].</dd>
</dl>
<p>Class methods may be invoked either via the class name or via an object of the class.
For example:</p>
<pre class="sh_tcl">
. class Account {balance 0}
Account
. Account methods
classname classvars destroy eval get method methods new vars
. set a [Account]
&lt;reference.&lt;Account&gt;.00000000000000000001&gt;
. $a methods
classname classvars destroy eval get method methods new vars
</pre>
<h2 id="predefined-object-methods">PREDEFINED OBJECT METHODS</h2>
<p>Decaring a class pre-defines a number of &ldquo;object&rdquo; methods. i.e. those which operate
on a specific object.</p>
<dl>
<dt><strong>destroy</strong></dt>
<dd>Destroys the object. This method may be overridden, but note that it should
delete the object with {rename $self &ldquo;&rdquo;}. This method will also be called
if the object is reaped during garbage collection.</dd>
</dl>
<dl>
<dt><strong>get</strong> varname</dt>
<dd>Returns the value of the given instance variable.</dd>
</dl>
<dl>
<dt><strong>eval</strong> ?locals? body</dt>
<dd>Makes any given local variables available to the body, along with
the instance variables, and evaluate the body in that context.
This can be used for one-off evaluation to avoid declaring a method.</dd>
</dl>
<h2 id="creating-objects">CREATING OBJECTS</h2>
<p>An object is created with the <code>new</code> method, or simply by using the classname shortcut.
If the <code>new</code> method is used, the variables for the newly created object (instance variables)
may be initialised. Otherwise they are set to the default values specified when the
class was declared.</p>
<p>For example:</p>
<pre class="sh_tcl">
. class Account {balance 0}
Account
. set a [Account]
&lt;reference.&lt;Account&gt;.00000000000000000001&gt;
. set b [Account new {balance 1000}]
&lt;reference.&lt;Account&gt;.00000000000000000002&gt;
. $a get balance
0
. $b get balance
1000
</pre>
<h2 id="declaring-methods">DECLARING METHODS</h2>
<p>In addition to the predefined methods, new methods may be decared, or existing
methods redefined with the class method, method.</p>
<p>Declaring a method is very similar to defining a proc, and the arglist
has identical syntax. For example:</p>
<pre class="sh_tcl">
. Account method show {{chan stdout}} { $chan puts "Balance of account is $balance" }
. $b show
Balance of account is 1000
</pre>
<p>All instance variables are available within the method and any
changes to these variables are maintained by the object.</p>
<p>In addition, the $self variables is defined and refers to the current object.
This may be used to invoke further methods on the object. For example:</p>
<pre class="sh_tcl">
. Account method show {} { puts "Balance of account is [$self get balance]" }
. $b show
Balance of account is 1000
</pre>
<p>Notes:</p>
<ul>
<li>It is a bad idea to unset an instance variable.</li>
<li>In general, you should avoid redefining any of the pre-defined methods, except for <code>destroy</code>.</li>
<li>When accessing the caller&rsquo;s scope with upvar or uplevel, note that there
are two frame levels between the caller and the method. Thus it is necessary
to use <code>upvar 2</code> or <code>uplevel 2</code></li>
</ul>
<h2 id="inheritance">INHERITANCE</h2>
<p>For each base class given in a new class declaration, the methods
and variables of those classes are imported into the new class being
defined. Base classes are imported in left to right order, so that if a
method is defined in more than one base class, the later definition
is selected. This applies similarly to class variables.</p>
<p>Within a method, <code>super</code> may be used to explicitly invoke a
base class method on the object. This applies only to the <em>last</em>
base class given. For example:</p>
<pre class="sh_tcl">
# Assumes the existence of classes Account and Client
. Account method debit {amount} { incr balance -$amount }
. class CreditAccount {Client Account} {type visa}
CreditAccount
. CreditAccount method debit {amount} {
puts "Debit $type card"
super debit $amount
}
. set a [CreditAccount]
&lt;reference.&lt;Account&gt;.00000000000000000001&gt;
. $a debit 20
Debit visa card
. $a balance
-20
</pre>
<p>In the CreditAccount debit method, the call to <code>super debit</code> invokes
the method <code>Account debit</code> since Account is the last base class listed.</p>
<h2 id="object-lifetimegarbage-collection">OBJECT LIFETIME/GARBAGE COLLECTION</h2>
<p>Objects are implemented as lambdas. That is, they are procedures with state
and are named as references. This means that when an object is no longer
reachable by any name and garbage collection runs, the object will be
discarded and the destructor will be invoked. Note that the garbage collector
can be invoked manually with <code>collect</code> if required.</p>
<pre class="sh_tcl">
. class Account {}
Account
. Account method destroy {} { puts dying...; rename $self "" }
Account destroy
. proc a {} { set b [Account]; return "" }
a
. a
. collect
dying...
1
</pre>
<h2 id="class-methodsclass-static-variables">CLASS METHODS/CLASS STATIC VARIABLES</h2>
<p>All methods defined with <code>method</code> operate on objects (instances).
If a class method is required, it is possible to simply declare one with <code>proc</code>.
The method dispatcher will automatically be able to dispatch to this method.
Using this approach, it is also possible to add class static variables by
defining static variables to the proc. Although strictly these variables
are accessible only to that proc, not the class as a whole.</p>
<p>For example:</p>
<pre class="sh_tcl">
. class Account {}
Account
. proc {Account nextid} {} {{id 0}} { incr id }
Account nextid
. Account nextid
1
. Account nextid
2
. set a [Account]
&lt;reference.&lt;Account&gt;.00000000000000000001&gt;
. $a nextid
3
. $a eval { $self nextid }
4
</pre>
<h2 id="how-method-dispatch-works">HOW METHOD DISPATCH WORKS</h2>
<p>All class and object methods are name &ldquo;classname methodname&rdquo;.</p>
<p>The class method dispatcher is named &ldquo;classname&rdquo;. When invoked with a methodname,
it simply invokes the method &ldquo;classname methodname&rdquo;.</p>
<p>The method dispatch is via a two step process. Firstly the object procedure is invoked
with the method name. This procedure then invokes &ldquo;classname method&rdquo; which sets up
the appropriate access to the object variables, and then invokes the method body.</p>
<h2 id="examples">EXAMPLES</h2>
<h3 id="treetclhttprepoorczwjimtclgitblobheadtreetcl"><a href="http://repo.or.cz/w/jimtcl.git/blob/HEAD:/tree.tcl">tree.tcl</a></h3>
<p>The <code>tree</code> package is implemented using the <code>oo</code> package.
See the source code in tree.tcl and a usage example in tests/tree.test</p>
<p>Of particular note is how callbacks and recursive invocation is used in the <code>walk</code> method.</p>
<h3 id="examplesootesttclhttprepoorczwjimtclgitblobheadexamplesootesttcl"><a href="http://repo.or.cz/w/jimtcl.git/blob/HEAD:/examples/ootest.tcl">examples/ootest.tcl</a></h3>
<p>A comprehensive OO example is provided in examples/ootest.tcl.</p>
<p>It can be run simply as:</p>
<pre class="sh_unix">
$ ./jimsh examples/ootest.tcl
</pre>
</div>
</div>
<div id="sidebar">
<h2>About Jim Tcl</h2>
<ul>
<li class="stdlink"><a href="/">Introduction</a></li>
<li class="newlink"><a href="/news/">News</a></li>
<li class="stdlink"><a href="/download/">Download</a></li>
<li class="stdlink"><a href="/documentation/">Documentation</a></li>
<li class="stdlink"><a href="/extensions/">Extensions</a></li>
<li class="stdlink"><a href="/license/">License</a></li>
<li class="stdlink"><a href="/about/">About</a></li>
</ul>
<h2>Community</h2>
<ul>
<li><a href="https://lists.berlios.de/mailman/listinfo/jim-devel">Mailing List</a></li>
<li><a href="https://github.com/msteveb/jimtcl">Jim on github</a></li>
<li><a href="http://wiki.tcl.tk/jim">Jim @ the Tcler's Wiki</a></li>
<li><a href="http://developer.berlios.de/projects/jim">Berlios Project Page</a></li>
</ul>
</div>
<script language="javascript">sh_highlightDocument();</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -1,285 +0,0 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Jim Tcl - Sqlite Extension</title>
<link rel="stylesheet" type="text/css" href="/css/style.css" media="screen">
<link rel="stylesheet" type="text/css" href="/css/sh_style.css" media="screen">
<script src="/javascript/sh_main.min.js" type="text/javascript"></script>
<script src="/javascript/sh_lang.js" type="text/javascript"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-23178588-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<meta name="generator" content="nanoc 3.1.6">
</head>
<body>
<div id="header">
<h1 id="blog-title">The Jim Interpreter</h1>
<p id="description">A small footprint implementation of the Tcl programming language</p>
</div>
<div id="content">
<div class="breadcrumbs">
<a href="/">The Jim Interpreter</a>
»
<a href="/documentation/">Documentation</a>
»
<a href="/documentation/sqlite/">Sqlite Extension</a>
</div>
<div class="main" id="main">
<h1 id="sqlite-support-for-jim-tcl">Sqlite Support for Jim Tcl</h1>
<h2 id="overview">OVERVIEW</h2>
<p>The sqlite and sqlite3 extensions makes possible to work with
<a href="http://www.sqlite.org">sqlite</a> databases from Jim. SQLite is a
small C library that implements a self-contained, embeddable,
zero-configuration SQL database engine. This means it is perfect
for embedded systems, and for stand-alone applications that need
the power of SQL without to use an external server like Mysql.</p>
<p><strong>Note:</strong> The same interface is exported for both the <strong>sqlite</strong> and <strong>sqlite3</strong>
extensions. The only difference being the open call, <strong>sqlite.open</strong> vs. <strong>sqlite3.open</strong></p>
<h2 id="basic-usage">Basic usage</h2>
<p>The Sqlite extension exports an Object Based interface for databases. In order
to open a database use:</p>
<pre class="sh_tcl">
set f [sqlite3.open dbname]
</pre>
<p>The <code>sqlite3.open</code> command returns a db handle, that is a command name that
can be used to perform operations on the database. A real example:</p>
<pre class="sh_tcl">
. set db [sqlite3.open test.db]
sqlite.handle0
. $db query "SELECT * from tbl1"
{one hello! two 10} {one goodbye two 20}
</pre>
<p>In the second line the handle is used as a command name, followed
by the &lsquo;method&rsquo; or &lsquo;subcommand&rsquo; (&ldquo;query&rdquo; in the example), and the arguments.</p>
<h2 id="the-query-method">The query method</h2>
<p>The query method has the following signature:</p>
<pre class="sh_tcl">
$db query SqlQuery ?args?
</pre>
<p>The sql query may contain occurrences of &ldquo;%s&rdquo; that are substituted
in the actual query with the following arguments, quoted in order
to make sure that the query is correct even if this arguments contain
&ldquo;&rsquo;&rdquo; characters. So for example it is possible to write:</p>
<pre class="sh_tcl">
. $db query "SELECT * from tbl1 WHERE one='%s'" hello!
{one hello! two 10}
</pre>
<p>Instead of hello! it is possible to use a string with embedded &ldquo;&rsquo;&rdquo;:</p>
<pre class="sh_tcl">
. $db query "SELECT * from tbl1 WHERE one='%s'" a'b
(no matches - the empty list is returned)
</pre>
<p>This does not work instead using the Tcl variable expansion in the string:</p>
<pre class="sh_tcl">
. $db query "SELECT * from tbl1 WHERE one='$foo'"
near "b": syntax error
</pre>
<p>In order to obtain an actual &lsquo;%&rsquo; character in the query, there is just
to use two, like in &ldquo;foo %% bar&rdquo;. This is the same as the [format] argument.</p>
<h2 id="specification-of-query-results">Specification of query results</h2>
<p>In one of the above examples, the following query was used:</p>
<pre class="sh_tcl">
. $db query "SELECT * from tbl1"
{one hello! two 10} {one goodbye two 20}
</pre>
<p>As you can see the result of a query is a list of lists. Every
element of the list represents a row, as a list of key/value pairs,
so actually every row is a Jim dictionary.</p>
<p>The following example and generated output show how to take advantage
of this representation:</p>
<pre class="sh_tcl">
. set res [$db query "SELECT * from tbl1"]
{one hello! two 10} {one goodbye two 20}
. foreach row $res {puts "One: $row(one), Two: $row(two)"}
One: hello!, Two: 10
One: goodbye, Two: 20
</pre>
<p>To access every row sequentially is very simple, and field of a row
can be accessed using the $row(field) syntax.</p>
<h2 id="the-close-method">The close method</h2>
<p>In order to close the db, use the &lsquo;close&rsquo; method that will have as side effect
to close the db and to remove the command associated with the db.
Just use:</p>
<pre class="sh_tcl">
$db close
</pre>
<h2 id="handling-null-values">Handling NULL values</h2>
<p>In the SQL language there is a special value NULL that is not the empty
string, so how to represent it in a typeless language like Tcl?
For default this extension will use the empty string, but it is possible
to specify a different string for the NULL value.</p>
<p>In the above example there were two rows in the &lsquo;tbl1&rsquo; table. Now
we can add usign the &ldquo;sqlite&rdquo; command line client another one with
a NULL value:</p>
<pre><code>sqlite&gt; INSERT INTO tbl1 VALUES(NULL,30);
sqlite&gt; .exit
</code></pre>
<p>That&rsquo;s what the sqlite extension will return for default:</p>
<pre class="sh_tcl">
. $db query "SELECT * from tbl1"
{one hello! two 10} {one goodbye two 20} {one {} two 30}
</pre>
<p>As you can see in the last row, the NULL is represented as {}, that&rsquo;s
the empty string. Using the -null option of the &lsquo;query&rsquo; command we
can change this default, and tell the sqlite extension to represent
the NULL value as a different string:</p>
<pre class="sh_tcl">
. $db query -null &lt;&lt;NULL&gt;&gt; "SELECT * from tbl1"
{one hello! two 10} {one goodbye two 20} {one &lt;&lt;NULL&gt;&gt; two 30}
</pre>
<p>This way if the emtpy string has some semantical value for your
dataset you can change it.</p>
<h2 id="finding-the-id-of-the-last-inserted-row">Finding the ID of the last inserted row</h2>
<p>This is as simple as:</p>
<pre class="sh_tcl">
. $db lastid
10
</pre>
<h2 id="number-of-rows-changed-by-the-most-recent-query">Number of rows changed by the most recent query</h2>
<p>This is also very simple, there is just to use the &lsquo;changes&rsquo; method
without arugments.</p>
<pre class="sh_tcl">
. $db changes
5
</pre>
<p>Note that if you drop an entire table the number of changes will
be reported as zero, because of details of the sqlite implementation.</p>
<p>That&rsquo;s all,
Enjoy!
Salvatore Sanfilippo</p>
<p>p.s. this extension is just the work of some hour thanks to the cool
clean C API that sqlite exports. Thanks to the author of sqlite for this
great work.</p>
<h2 id="in-memory-databases">In memory databases</h2>
<p>SQLite is able to create in-memory databases instead to use files.
This is of course faster and does not need the ability to write
to the filesystem. Of course this databases are only useful for
temp data.</p>
<p>In-memory DBs are used just like regular databases, just the name used to
open the database is :memory:. That&rsquo;s an example that does not use the
filesystem at all to create and work with the db.</p>
<pre class="sh_tcl">
package require sqlite3
set db [sqlite3.open :memory:]
$db query {CREATE TABLE plays (id, author, title)}
$db query {INSERT INTO plays (id, author, title) VALUES (1, 'Goethe', 'Faust');}
$db query {INSERT INTO plays (id, author, title) VALUES (2, 'Shakespeare', 'Hamlet');}
$db query {INSERT INTO plays (id, author, title) VALUES (3, 'Sophocles', 'Oedipus Rex');}
set res [$db query "SELECT * FROM plays"]
$db close
foreach r $res {puts $r(author)}
</pre>
<p>Of course once the Jim process is destroyed the database will no longer
exists.</p>
</div>
</div>
<div id="sidebar">
<h2>About Jim Tcl</h2>
<ul>
<li class="stdlink"><a href="/">Introduction</a></li>
<li class="newlink"><a href="/news/">News</a></li>
<li class="stdlink"><a href="/download/">Download</a></li>
<li class="stdlink"><a href="/documentation/">Documentation</a></li>
<li class="stdlink"><a href="/extensions/">Extensions</a></li>
<li class="stdlink"><a href="/license/">License</a></li>
<li class="stdlink"><a href="/about/">About</a></li>
</ul>
<h2>Community</h2>
<ul>
<li><a href="https://lists.berlios.de/mailman/listinfo/jim-devel">Mailing List</a></li>
<li><a href="https://github.com/msteveb/jimtcl">Jim on github</a></li>
<li><a href="http://wiki.tcl.tk/jim">Jim @ the Tcler's Wiki</a></li>
<li><a href="http://developer.berlios.de/projects/jim">Berlios Project Page</a></li>
</ul>
</div>
<script language="javascript">sh_highlightDocument();</script>
</body>
</html>

View File

@ -27,7 +27,6 @@ puts "
</tr>
"
setting_toggle "theTVDB.com integration?" "tvdb" $($tvdb)
setting_toggle "Slide-down toolbar?" "notoolbar" $(!$notoolbar) 1
setting_toggle "Mobile link on main page?" "nomobile" $(!$nomobile) 1
setting_toggle "Help links on main page?" "nohelplinks" $(!$nohelplinks) 1

View File

@ -0,0 +1,44 @@
######################################################################
# TheTVDB Settings
puts "
<h4>TheTVDB Integration Settings</h4>
<div><fieldset style=\"display: inline\">
<legend>
TheTVDB Integration Settings
</legend>
<table>
"
setting_toggle "Enable integration?" "tvdb" $tvdb
setting_toggle "Additional diagnostic output?" "tvdb_debug" $tvdb_debug
puts "
<tr>
<form class=auto id=dedup method=get action=$env(SCRIPT_NAME)>
<th class=key>
Dedup Episode Prefix<br>
<span class=footnote>
%s - series number<br>
%e - episode number<br>
%E - number of episodes
</span>
</th>
<td>
<input name=dedup_template value=\"$dedup_template\"
class=\"text ui-widget-content ui-corner-all\"
length=20 maxlength=50>
<small>
<input id=dedup_submit value=\"change\" type=submit>
</small>
<div id=dedup_output></div>
</td>
</form>
</tr>
"
puts "
</table></fieldset></div>
"

View File

@ -39,6 +39,7 @@ set epg_style [$settings epg_style]
set service_style [$settings service_style]
set notoolbar [$settings notoolbar]
set tvdb [$settings tvdb]
set tvdb_debug [$settings tvdb_debug]
set nomobile [$settings nomobile]
set nohelplinks [$settings nohelplinks]
set notwitfeed [$settings notwitfeed]
@ -52,6 +53,7 @@ set autolog [$settings autolog]
set pkgdev [$settings pkgdev]
set logsize [$settings logsize]
set logkeep [$settings logkeep]
set dedup_template [$settings dedup_template]
# Handle updates
@ -79,8 +81,8 @@ proc handle_int_update {var old {text "Value"}} {
_handle_update digit $var $old $text
}
proc handle_str_update {var old {text "Value"}} {
_handle_update alnum $var $old $text
proc handle_str_update {var old {text "Value"} {class alnum}} {
_handle_update $class $var $old $text
}
handle_str_update hostname $hostname Hostname
@ -94,6 +96,7 @@ handle_int_update logsize $logsize "Log rotation size"
handle_int_update logkeep $logkeep "Logs to keep"
handle_int_update notoolbar $notoolbar "Disable toolbar"
handle_int_update tvdb $tvdb "Enable tvdb"
handle_int_update tvdb_debug $tvdb_debug "Enable tvdb debugging"
handle_int_update nomobile $nomobile "Disable mobile link"
handle_int_update nohelplinks $nohelplinks "Disable help links"
handle_int_update notwitfeed $notwitfeed "Disable twitter feed ticker"
@ -103,6 +106,7 @@ handle_int_update nounwatchedcount $nounwatchedcount "Disable unwatched count"
handle_int_update genrededup $genrededup "Genre search dedup"
handle_int_update autolog $autolog "Auto-processing log level"
handle_int_update audiomp3 $audiomp3 "MP3 type"
handle_str_update dedup_template $dedup_template "Dedup Template" print
set acluser [cgi_get acluser "-"]
set aclpass [cgi_get aclpass "-"]
@ -166,9 +170,11 @@ proc setting_toggle {name attr checked {invert 0} {val 0}} {
# Settings Modules
set moddir /mod/webif/html/settings/modules
foreach mod {general web epg network advanced} {
foreach mod {general tvdb web epg network advanced} {
if {[file exists "$moddir/$mod/.disabled"]} continue
catch {source "$moddir/$mod/settings.hook"}
if {[catch {source "$moddir/$mod/settings.hook"} msg]} {
puts "ERROR: $msg"
}
}
######################################################################

View File

@ -92,6 +92,13 @@ proc {dir iconset} {dir} {
lappend attrs "autoexpire=1"
}
set tvdb 0
if {[file exists "$dir/.tvdbseriesid"]} {
set tvdb 1
lappend icons [_addicon "/img/tvdb-sm.png" "TheTVDB"]
lappend attrs "tvdb=1"
}
eval_plugins diriconset
return [list $icons $attrs]

View File

@ -25,6 +25,7 @@ class settings {
pkgdev 0
notoolbar 0
tvdb 0
tvdb_debug 0
nomobile 0
nohelplinks 0
notwitfeed 0
@ -113,7 +114,7 @@ settings method _nval_setting {name {val -1}} {
settings method _tval_setting {name {val -1}} {
global settingsdb
if {$val == -1} {
if {$val eq "-1"} {
# Get
set res [$settingsdb query "
select tval from settings
@ -173,6 +174,10 @@ settings method tvdb {{val -1}} {
return [$self _nval_setting tvdb $val]
}
settings method tvdb_debug {{val -1}} {
return [$self _nval_setting tvdb_debug $val]
}
settings method genrededup {{val -1}} {
return [$self _nval_setting genrededup $val]
}
@ -350,3 +355,9 @@ settings method logkeep {{num -1}} {
return $val
}
settings method dedup_template {{pattern -1}} {
set val [$self _tval_setting dedup_template $pattern]
if {$val eq "0"} { set val "s%se%e - " }
return $val
}

View File

@ -515,21 +515,11 @@ set ::ts::episode_prefixes {
{, Part [0-9]}
}
ts method tvdb_resolve {} {
ts method _tvdb_resolve {seriesid} {
# See if we can find a TVDB series for this recording.
set dir [file dirname $file]
set seriesid 0
if {[file exists "$dir/.tvdbseriesid"]} {
set seriesid [string trim [file read "$dir/.tvdbseriesid"]]
} else {
return
}
if {!$seriesnum && [file exists "$dir/.tvdbseries"]} {
set seriesnum [string trim [file read "$dir/.tvdbseries"]]
}
set tvdb_series [set v [tvdb series [$self series_name] $seriesid]]
if {[$v get seriesid] == 0} { return }
@ -637,24 +627,44 @@ ts method episode_name {} {
# Now see if TVDB has anything to add
if {[system has tvdb]} {
set tvdb_data [$self tvdb_resolve]
if {[dict exists $tvdb_data name]} {
if {!$seriesnum} { set seriesnum $tvdb_data(series) }
if {!$episodenum} { set episodenum $tvdb_data(episode) }
return $tvdb_data(name)
}
set fbase "[file dirname $file]/.tvdb"
if {![system has tvdb] || ![file exists "${fbase}seriesid"]} {
return $s
}
if {!$seriesnum && [file exists "${fbase}series"]} {
set seriesnum [string trim [file read "${fbase}series"]]
}
foreach seriesid [\
string trim [split [file read "${fbase}seriesid"] "\n"]] {
set tvdb_data [$self _tvdb_resolve $seriesid]
if {![dict exists $tvdb_data name]} continue
if {!$seriesnum} { set seriesnum $tvdb_data(series) }
if {!$episodenum} { set episodenum $tvdb_data(episode) }
return $tvdb_data(name)
}
return $s
}
ts method epstr {} {
set x s
if {$seriesnum eq 0} { append x "?" } else { append x $seriesnum }
append x e
if {$episodenum eq 0} { append x "??" } else { append x $episodenum }
if {$episodetot ne 0} { append x "/$episodetot" }
return $x
ts method epstr {{format "s%se%e/%E"}} {
set map {}
if {$seriesnum eq 0} {
set map(%s) "?"
} else {
set map(%s) $seriesnum
}
if {$episodenum eq 0} {
set map(%e) "??"
} else {
set map(%e) [format "%02d" $episodenum]
}
if {$episodetot eq 0} {
set map(%E) "?"
} else {
set map(%E) $episodetot
}
return [string map $map $format]
}

View File

@ -213,11 +213,10 @@ tvdb method dbhandle {} {
return $db
}
proc {tvdb tolike} {str} {
return "%[string map {
" and " "%"
" the " "%"
} $str]%"
proc {tvdb tolike} {str {extra ""}} {
set map {" and " "%" " the " "%"}
if {[llength $extra]} { lappend map {*}$extra }
return "%[string map $map $str]%"
}
tvdb method episodebynum {series episode} {
@ -231,12 +230,22 @@ tvdb method episodebynum {series episode} {
tvdb method episodebyname {str {series 0} {episode 0}} {
if {![llength [set db [$self dbhandle]]]} return {}
set q "select * from episode where name like '%s'"
if {$series} { append q " and series = $series" }
if {$episode} { append q " and episode = $episode" }
append q " order by length(name)"
append q " order by length(name) desc"
set ret [$db query $q [tvdb tolike $str]]
if {[llength $ret]} { return [lindex $ret 0] }
# Try a match with all spaces removed
set q "select * from episode where replace(name, ' ', '') like '%s'"
if {$series} { append q " and series = $series" }
if {$episode} { append q " and episode = $episode" }
append q " order by length(name) desc"
set ret [$db query $q [tvdb tolike $str {" " ""}]]
if {[llength $ret]} { return [lindex $ret 0] }
return {}
}