Kodi Community Forum

Full Version: force scanfolder
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
i am trying to create an addon that given a list of paths will scan for new tv episodes
the problem i am facing is the scan does not seem to be working properly.
I have it at the moment where it does scan each path, but think its not waiting for
previous path to finish scanning, hence i think its not working properely.

Code:
import sys
import os
import subprocess
import xbmc, xbmcaddon,xbmcgui



xaddon = xbmcaddon.Addon(id='script.runmyscan')
addonpath = xaddon.getAddonInfo('path')


if xbmc.getCondVisibility('Library.IsScanning'):
    dialog = xbmcgui.Dialog()
    dialog.ok('Scanning..', "Scan is already running. Stop Current Scan and try again")
else:

    
    text_file = open(addonpath + "/paths.txt", "r")
    #lines = text_file.readlines()
    lines = text_file.read().split('\n')
    print lines

    for path in lines:
        #print path

        xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "method": "VideoLibrary.Scan", "params": {"directory": "' + path + '" }, "id": 1 }}')
        xbmc.sleep(200)
        while xbmc.getCondVisibility('Library.IsScanning'):
            xbmc.sleep(200)

        xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "method": "VideoLibrary.Scan", "id": 1 }}')

can anyone help.

thanks
(2014-09-13, 11:13)k_zeon Wrote: [ -> ]but think its not waiting for previous path to finish scanning, hence i think its not working properely.
I've had the same issue. If you call scan while it's already scanning it will actually do the oposite: stop the current scan. The getCondVisibility call is unreliable, so what you should to is use Monitor.onDatabaseScanStarted and onDatabaseUpdated (called when scan starts/stops, don't mind the names) and create a locking mechanism of sort to make sure the scan has finished before executing next scan.
hi takoi. do you have any sample scripts to show.
would help alot.

thanks
bump. anybody ?
You'll have to write it yourself. Your script should (mostly) work if you just increase the time in the first xbmc.sleep call. You can see how I've done it here. Though I highly recommend not doing it like this, but use Monitor as I said. (I only do it like this because I need to handle cleaning)
hi takoi. I tried to find any examples how to use Monitor.onDatabaseScanStarted and onDatabaseUpdated
but have not really found anything of use.
Do you have an example of these commands that i could learn from.

thanks
There is plugin called as I remember "missing movie plugin"which do exactly the same for movies
thanks Marx1. took a look but does not have anything that can help me. thanks anyway
bump. anyone else.?
Monitor pydocs: http://mirrors.xbmc.org/docs/python-docs...ml#Monitor

I would subclass Monitor and in __init__ create a variable self.isupdating = False. Then override onDatabaseScanStarted() and set that variable to True, override onDatabaseUpdated() to set it to False. You may want to instantiate your Monitor subclass in it's own thread.

Then, instead of querying with GetCondVisibility, you would instead query your Monitor's .isupdating variable.

Just a thought.
(2014-09-21, 17:17)KenV99 Wrote: [ -> ]Monitor pydocs: http://mirrors.xbmc.org/docs/python-docs...ml#Monitor

I would subclass Monitor and in __init__ create a variable self.isupdating = False. Then override onDatabaseScanStarted() and set that variable to True, override onDatabaseUpdated() to set it to False. You may want to instantiate your Monitor subclass in it's own thread.

Then, instead of querying with GetCondVisibility, you would instead query your Monitor's .isupdating variable.

Just a thought.

Sounds like what i need. I have never coded anything except the default.py file.
I don't know how to create a seperate thread to subclass.

I am willing to learn, and usually can look at a basic example and adjust to my needs
but i have not seen any addon that does this.

Python is not my best language in programming.
Something like this:

Code:
import threading
import xbmc
dbmonitor = None


class XbmcMonitor (xbmc.Monitor):

    def __init__(self):
        xbmc.Monitor.__init__(self)
        self.isupdating = False

    def onDatabaseScanStarted(self, database):
        self.isupdating = True
        xbmc.log('######## Scan started thread: %s' % str(threading.current_thread().ident), level=xbmc.LOGNOTICE)

    def onDatabaseUpdated(self, database):
        self.isupdating = False
        xbmc.log('######## Scan ended thread: %s' % str(threading.current_thread().ident), level=xbmc.LOGNOTICE)


def threadstart():
    global dbmonitor
    dbmonitor = XbmcMonitor()
    while not xbmc.abortRequested:
        xbmc.sleep(250)


def main():
    thread = threading.Thread(target=threadstart)
    thread.start()
    xbmc.sleep(1000)
    while not xbmc.abortRequested:
        if dbmonitor.isupdating is True:
            xbmc.log('######### DB updating thread: %s' % str(threading.current_thread().ident), level=xbmc.LOGNOTICE)
        xbmc.sleep(500)

EDIT: I rewrote it without multiple inheritance and added some logging to demonstrate that the monitor and the main are in different threads. You need to call the thread with the typical loop for xbmc.AbortRequested to keep the thread alive... Tried it using daemon=True and that didn't seem to work.


Docs:
http://pymotw.com/2/threading/
https://docs.python.org/2/library/thread...ad-objects
(2014-09-22, 22:39)KenV99 Wrote: [ -> ]Something like this:

Yes, it uses multiple inheritance Undecided. If that is worry, create a separate class that only subclasses 'threading.Thread' and then instantiate the monitor in that class when you override run() - see the links below.

Docs:
http://pymotw.com/2/threading/
https://docs.python.org/2/library/thread...ad-objects
But why do you need a thread? You don't have a run method so inheriting from Thread does absolutely nothing. Also, since you toggle the isupdating flag, you will have exactly the same issues as using getCondVisibility: you can't trust it call next scan like OP wanted. Here's a different example (pseudocode, not tested):

Code:
class MyCallbackHandler(xbmc.Monitor):
    def __init__(self):
        xbmc.Monitor.__init__(self)
        self.scan_complete = False

    def onDatabaseUpdated(self, library):
        self.scan_complete = True


monitor = MyCallbackHandler()

for path in paths:
    xbmc.executeJSONRPC('...')

    # wait for scan to complete
    while not monitor.scan_complete:
        xbmc.sleep(..)

    # important thing is to reset the flag here, before next call to scan, so you *know* it will toggled again only when it finish
    monitor.scan_complete = False
(2014-09-13, 13:17)takoi Wrote: [ -> ]
(2014-09-13, 11:13)k_zeon Wrote: [ -> ]but think its not waiting for previous path to finish scanning, hence i think its not working properely.
I've had the same issue. If you call scan while it's already scanning it will actually do the oposite: stop the current scan. The getCondVisibility call is unreliable, so what you should to is use Monitor.onDatabaseScanStarted and onDatabaseUpdated (called when scan starts/stops, don't mind the names) and create a locking mechanism of sort to make sure the scan has finished before executing next scan.

(2014-09-23, 14:00)takoi Wrote: [ -> ]
(2014-09-22, 22:39)KenV99 Wrote: [ -> ]Something like this:

Yes, it uses multiple inheritance Undecided. If that is worry, create a separate class that only subclasses 'threading.Thread' and then instantiate the monitor in that class when you override run() - see the links below.

Docs:
http://pymotw.com/2/threading/
https://docs.python.org/2/library/thread...ad-objects
But why do you need a thread? You don't have a run method so inheriting from Thread does absolutely nothing. Also, since you toggle the isupdating flag, you will have exactly the same issues as using getCondVisibility: you can't trust it call next scan like OP wanted. Here's a different example (pseudocode, not tested):

Code:
class MyCallbackHandler(xbmc.Monitor):
    def __init__(self):
        xbmc.Monitor.__init__(self)
        self.scan_complete = False

    def onDatabaseUpdated(self, library):
        self.scan_complete = True


monitor = MyCallbackHandler()

for path in paths:
    xbmc.executeJSONRPC('...')

    # wait for scan to complete
    while not monitor.scan_complete:
        xbmc.sleep(..)

    # important thing is to reset the flag here, before next call to scan, so you *know* it will toggled again only when it finish
    monitor.scan_complete = False

Hmmmm... I thought it was YOU had suggested to use onDatabaseScanStarted, etc. as a more reliable method (see above). I don't use these events myself.

Why a separate thread? I suggested it to avoid having to insert xbmc.sleep in the code prior to each time you check to see if the database is updating. If you don't do that then your own main thread may not release control to allow the onDatabaseScanStarted and onDatabaseUpdated events to update the .isupdating variable.

PS: While you were posting, I was editing the code I had posted when I realized there wasn't actually a separate thread running with the way I originally wrote the example code.
(2014-09-23, 14:09)KenV99 Wrote: [ -> ]I suggested it to avoid having to insert xbmc.sleep in the code prior to each time you check to see if the database is updating. If you don't do that then your own main thread may not release control to allow the onDatabaseScanStarted and onDatabaseUpdated events to update the .isupdating variable.
But you do have a xbmc.sleep in your main thread... (in the new example too). You can't block the main thread regardless, so it makes no difference if Monitor was created on a thread or not.

The problem is that .isupdating may be True for e.g. 1ns, if the scan only took 1ns. If you just check it periodically, you will most likely miss it.
Same if isupdating was false in one instance, that doesn't mean it will be false the next too. If you call 'VideoLibrary.Scan' you risk canceling the previous call. That's exactly the problem with getCondVisibility.

My suggestion was more general use these methods to "create a locking mechanism of sort", but I realize using actual locks will probably never work. The whole Monitor is really retarded and will deadlock if you even try to use locks and events.
Pages: 1 2