Dap: Prevent misleading exceptions in LoadFromDevice()

In some systems such as mine, when you connect a device, and after
that, you switch it from MTP mode to PTP mode, it could happen that
two events for the same device, one for mapping and the other for
unmapping, could arrive almost at the same time:

[19 Debug 23:43:39.175] Found DAP support (Banshee.Dap.Mtp.MtpSource) for device Nexus 4 and Uuid /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2
[20 Debug 23:43:39.175] Unmapping DAP source (/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2)

The Unmap one was causing a call to DapSource.Dispose() which, in
this case it set MtpSource.mtp_device to null, which would then
generate an ArgumentNullException when trying to enter into a
lock(), because the LoadFromDevice() method was still in progress
(fired by the Map event).

These 2 events coming together is very inconvinient because the
load process (LoadDeviceContents()) is threaded, so if we need
that the Unmap event interrupts the load process of the Map event,
an exception will definitely happen. However, it's better that
this exception is comprehensible instead of misleading, and for
that we're going to use Thread.Abort() API which will generate
a ThreadAbortException, rather than an ArgumentNullException or
other even more misleading...
DapSource: remove unneeded overriden properties

They were simply calling to their base counterparts so it is
safe to remove them.
DapService: avoid freezing Banshee when unmapping device (bgo#723040)

It could happen that a Map event generated a process that
could take a while to detect the device, which would hold the
DapService.sync lock, which is also used by the Unmap events,
and the latter events run in the main thread, so this could
mean that banshee gets frozen for a time as long as it takes
to detect/connect to the device.

To fix this we simply need to spawn a thread for the Unmap
operation. This thread will later call ThreadAssist API again
to come back to the main thread when the UI needs to be
changed, but that's ok. On top of that, the Dispose() was
actually being called outside this ThreadAssist.ProxyToMain()
call, so it was generating bad gui-thread-check traces, so
it's a good time to fix this as well.
Updated Galician translations
Notifications: improve null check before AttachToWidget() (bgo#723889)

GtkNotificationArea class returns null always for its Widget property,
which means that every user of INotificationAreaBox should check if
it's null before dereferencing it, not only check if the object is
null.

This was not happening and was causing an apparently harmless warning
to be printed in the console. The warning didn't have enough info
about the exception so now the .Exception() method is used instead,
which prints the whole stacktrace. (This has been changed in
SoundMenuService as well, for consistency.)

This didn't seem to happen in the stable branch because in there the
class used as an INotificationAreaBox is X11NotificationAreaBox, which
seems to be deprecated in master. Nonetheless, this fix should be
backported too because X11NotificationAreaBox seemed to be only used
in the Linux platform, so by backporting it we may be fixing the
issue in other platforms.
Updated Lithuanian translation
MediaEngineTests: fix warnings
ThickClient: avoid using Console.WriteLine() directly

If we want to print a stacktrace, the best way to do it is
rather using Hyena.Log.Exception() API.
Shuffler: fix Repeat-OFF mode when Shuffle is ON (bgo#724515)

Shuffler should only retry calling GetRandomTrack() when
the previous call returned null and repeat is ON, regardless
of the shuffle mode.
Shuffler: fix shuffle for 2 tracks when repeat is enabled (bgo#671221)

Use last_track.LastPlayed datetime value instead of last_random,
because it would avoid a glitch about the way the current logic
resets the RandomByTrack mode.

We can explain this glitch by explaining here the hypothetical
sequence of events of 2 tracks being played, whose duration is
exactly 1 minute each:

0:00 play track1 manually
--
0:58 requestnexttrack fired, lastplayedstamp of track1 updated to 0:58
0:59 query to find a random track from a set which have lastplayedstamp < 0:00 , found track2
0:59 chosen track2, set last_random to 0:59
1:00 track2 begins to play, lastplayedstamp of track1 updated to 1:00
--
1:58 requestnexttrack fired, lastplayedstamp of track2 updated to 1:58
1:59 query to find a random track from a set which have lastplayedstamp < 0:00 , found nothing
1:59 query to find a random track from a set which have lastplayedstamp < 0:59 (last_random) , found nothing

This glitch makes the Repeat-All mode not work when the source to
play has 2 tracks, as you just have seen. If we add a 3rd track to
the mix, the random mode is sub-optimal, but at least the Repeat-All
mode works, and here would be the sequence of events:

0:00 play track1 manually
--
0:58 requestnexttrack fired, lastplayedstamp of track1 updated to 0:58
0:59 query to find a random track from a set which have lastplayedstamp < 0:00 , found track2 & track3
0:59 chosen track2, set last_random to 0:59
1:00 track2 begins to play, lastplayedstamp of track1 updated to 1:00
--
1:58 requestnexttrack fired, lastplayedstamp of track2 updated to 1:58
1:59 query to find a random track from a set which have lastplayedstamp < 0:00 , found track3
1:59 chosen track3, set last_random to 1:59
2:00 track3 begins to play, lastplayedstamp of track2 updated to 2:00
--
2:58 requestnexttrack fired, lastplayedstamp of track3 updated to 2:58
2:59 query to find a random track from a set which have lastplayedstamp < 0:00, found nothing
2:59 query to find a random track from a set which have lastplayedstamp < 1:59 (last_random) , found track1
2:59 chosen track1 , set last_random to 2:59
3:00 track1 begins to play, lastplayedstamp of track3 updated to 3:00
...


Partial fix for bgo#671221 (when there are 2 tracks to play)
Shuffler: fix shuffle for 1 track when repeat is enabled (bgo#671221)

Retry a third time when GetRandomTrack() returns null for a second
time. It can happen, because the first retry still tries to reset
the random mode but discarding the last track, to avoid duplicate
playbacks.

Fixes last part of bgo#671221 (when there is 1 track to play)
Gapless: fix smooth transition for RepeatSingle mode (bgo#627391)

RepeatSingle mode was setting the next track with OpenPlay() instead
of using SetNextTrack() when receiving the RequestNextTrack event,
which meant that the track to play next was not received in time*,
and therefore not succeed in making the transition gapless.

* The consequence of this was the following debug message:
[23 Debug 21:47:47.275] [Gapless] Timed out while waiting for next_track_set to be raised
Dap: avoid NullReferenceException at shutdown if Mtp mounted (bgo#724645)

Give up unmapping device if DapService is already disposed...
Dap: fix several issues with the Disconnect operation (bgo#724656)

DapInfoBar was not being destroyed on the main thread, which
could lead to crashes (I've seen some platforms more prone
to crash with this than others). Fixing this exposed other
synchronization issues, such as not checking for null in the
same thread as the one doing the operation on a widget, and
looping over a collection which could be modified, in which
case we need to make a copy of it before iterating.
DapInfoBar: avoid accessing multiple times to same property

These DapSource properties could take a while to retrieve and
they could be using locks (like in the case of MtpSource), so
it's more efficient to read them just once.
IO: protect Directory class against NREs via ArgumentNullExceptions
Mtp: show tracks which are in subfolders from Music/ (bgo#724678)

Files can happen to be in a hierarchy of folders inside the
Music/ folder in the device. To be able to see them we need
to do add them the proper MtpTrackInfo.MediaAttriubutes by
looking for them recursively.

Based on original patch by IBBoard <dev@ibboard.co.uk> (his
patch included read-and-write support, this patch only
implements read support for now. Write support will need
more discussion. See BGO#539804 for the latter.)
Mtp: avoid aborting thread while using libmtp (bgo#724730)

While the change in 37cb8a36f0a5884936fde0c84e7a9da87d19794a
was desirable to avoid misleading exceptions being thrown, it
exposed a situation that could not happen before that change:
the load thread being aborted in the middle of a libmtp access
(mtp_device field usage), because before that change, the load
thread would just be aborted when trying to access a null lock
(which means, the thread could only aborted outside when
running outside the mtp_device lock, which was more desirable).

In order to avoid this situation, we can make the DapSource
parent class hook on its child's lock by using a virtual
property that the child will map to its internal lock. This
way, we will only kill the load_thread when we have the lock
held (so no other thread is using mtp_device field).
Booter: remove obsolete commented lines about Mono SGEN

Mono ended up defaulting to SGEN for v3.2.x or higher, so we rather
simply let the underlying system decide.