1from gi.repository import GLib 2import pytest 3 4from xl.player.track_fader import TrackFader, FadeState 5 6NoFade = FadeState.NoFade 7FadingIn = FadeState.FadingIn 8Normal = FadeState.Normal 9FadingOut = FadeState.FadingOut 10 11 12class FakeStream: 13 def __init__(self): 14 self.reset() 15 16 def reset(self): 17 self.position = 0 18 self.volume = 42 19 self.fadeout_begin = False 20 self.stopped = False 21 22 def get_position(self): 23 return self.position 24 25 def set_volume(self, value): 26 self.volume = int(value * 100) 27 28 def stop(self): 29 self.stopped = True 30 31 def on_fade_out(self): 32 self.fadeout_begin = True 33 34 35class FakeTrack: 36 def __init__(self, start_off, stop_off, tracklen): 37 self.tags = { 38 '__startoffset': start_off, 39 '__stopoffset': stop_off, 40 '__length': tracklen, 41 } 42 43 def get_tag_raw(self, t): 44 return self.tags[t] 45 46 47# TODO: monkeypatch instead 48timeout_args = [()] 49 50 51def glib_timeout_add(*args): 52 timeout_args[0] = args[2:] 53 return args[1] 54 55 56def glib_source_remove(src_id): 57 pass 58 59 60GLib.timeout_add = glib_timeout_add 61GLib.source_remove = glib_source_remove 62 63TmSt = 1 64TmEx = 2 65 66 67# Test data: 68# Position, Volume, State, TmSt/TmEx/None, [call, [arg1...]] 69 70# fmt: off 71@pytest.mark.parametrize('test', [ 72 73 # Test don't manage the volume 74 [ 75 (0, 100, NoFade, None, 'play', None, None, None, None), 76 (1, 100, NoFade, None, 'pause'), 77 (2, 100, NoFade, None, 'unpause'), 78 (3, 100, NoFade, None, 'seek', 4), 79 (4, 100, NoFade, None, 'stop'), 80 (5, 100, NoFade, None), 81 ], 82 83 # Test fading in 84 [ 85 (0, 0, FadingIn, TmEx, 'play', 0, 2, None, None), 86 (1, 50, FadingIn, TmEx, 'execute'), 87 (3, 100, NoFade, None, 'execute'), 88 (4, 100, NoFade, None), 89 (5, 100, NoFade, None, 'stop'), 90 (6, 100, NoFade, None), 91 ], 92 93 # Test fading in: pause in middle 94 [ 95 (0, 0, FadingIn, TmEx, 'play', 0, 2, None, None), 96 (1, 50, FadingIn, TmEx, 'execute'), 97 (1, 50, FadingIn, None, 'pause'), 98 (1, 50, FadingIn, TmEx, 'unpause'), 99 (1, 50, FadingIn, TmEx, 'execute'), 100 (3, 100, NoFade, None, 'execute'), 101 (4, 100, NoFade, None), 102 (5, 100, NoFade, None, 'stop'), 103 (6, 100, NoFade, None), 104 ], 105 106 # Test fading in past the fade point 107 [ 108 (3, 100, NoFade, None, 'play', 0, 2, None, None), 109 (4, 100, NoFade, None), 110 (5, 100, NoFade, None, 'stop'), 111 (6, 100, NoFade, None), 112 ], 113 114 # Test fading out 115 [ 116 (3, 100, Normal, TmSt, 'play', None, None, 4, 6), 117 (4, 100, FadingOut, TmEx, 'start'), 118 (5, 50, FadingOut, TmEx, 'execute'), 119 (6, 0, FadingOut, TmEx, 'execute'), 120 (6.1, 0, NoFade, None, 'execute'), 121 (7, 0, NoFade, None), 122 ], 123 124 # Test all of them 125 [ 126 (0, 0, FadingIn, TmEx, 'play', 0, 2, 4, 6), 127 (1, 50, FadingIn, TmEx, 'execute'), 128 (3, 100, Normal, TmSt, 'execute'), 129 (4, 100, FadingOut, TmEx, 'start'), 130 (5, 50, FadingOut, TmEx, 'execute'), 131 (6, 0, FadingOut, TmEx, 'execute'), 132 (6.1, 0, NoFade, None, 'execute'), 133 (7, 0, NoFade, None), 134 ], 135 136 # Test fading in with startoffset 137 # [ 138 # (0, 0, FadingIn, TmEx, 'play', 60, 62, 64, 66), 139 # (0, 0, FadingIn, TmEx, 'seek', 60), 140 # (61, 50, FadingIn, TmEx, 'execute'), 141 # ], 142]) 143# fmt: on 144def test_fader(test): 145 146 # Test fade_out_on_play 147 148 # Test setup_track 149 150 # Test setup_track is_update=True 151 152 # Test unexpected fading out 153 154 check_fader(test) 155 156 157def check_fader(test): 158 stream = FakeStream() 159 fader = TrackFader(stream, stream.on_fade_out, 'test') 160 161 for data in test: 162 print(data) 163 now = data[0] 164 stream.position = int(now * TrackFader.SECOND) 165 print(stream.position) 166 volume = data[1] 167 state = data[2] 168 timer_id = data[3] 169 170 if len(data) > 4: 171 action = data[4] 172 args = data[5:] if len(data) > 5 else () 173 174 if action == 'start': 175 action = '_on_fade_start' 176 elif action == 'execute': 177 action = '_execute_fade' 178 args = timeout_args[0] 179 fader.now = now - 0.010 180 181 # Call the function 182 getattr(fader, action)(*args) 183 184 # Check to see if timer id exists 185 if timer_id is None: 186 assert fader.timer_id is None 187 elif timer_id == TmSt: 188 assert fader.timer_id == fader._on_fade_start 189 elif timer_id == TmEx: 190 assert fader.timer_id == fader._execute_fade 191 else: 192 assert False 193 194 assert fader.state == state 195 assert stream.volume == volume 196 197 198def test_calculate_fades(): 199 fader = TrackFader(None, None, None) 200 201 # fin, fout, start_off, stop_off, tracklen; 202 # start, start+fade, end-fade, end 203 calcs = [ 204 # fmt: off 205 206 # one is zero/none 207 (0, 4, 0, 0, 10, 0, 0, 6, 10), 208 (None, 4, 0, 0, 10, 0, 0, 6, 10), 209 210 # other is zero/none 211 (4, 0, 0, 0, 10, 0, 4, 10, 10), 212 (4, None, 0, 0, 10, 0, 4, 10, 10), 213 214 # both are equal 215 (4, 4, 0, 0, 10, 0, 4, 6, 10), 216 217 # both are none 218 (0, 0, 0, 0, 10, 0, 0, 10, 10), 219 (None, None, 0, 0, 10, 0, 0, 10, 10), 220 221 # Bigger than playlen: all three cases 222 (0, 4, 0, 0, 2, 0, 0, 0, 2), 223 (4, 0, 0, 0, 2, 0, 2, 2, 2), 224 (4, 4, 0, 0, 2, 0, 1, 1, 2), 225 226 # With start offset 227 (4, 4, 1, 0, 10, 1, 5, 6, 10), 228 229 # With stop offset 230 (4, 4, 0, 9, 10, 0, 4, 5, 9), 231 232 # With both 233 (2, 2, 1, 9, 10, 1, 3, 7, 9), 234 235 # With both, constrained 236 (4, 4, 4, 8, 10, 4, 6, 6, 8), 237 (2, 4, 4, 7, 10, 4, 5, 5, 7), 238 (4, 2, 4, 7, 10, 4, 6, 6, 7), 239 # fmt: on 240 ] 241 242 i = 0 243 for fin, fout, start, stop, tlen, t0, t1, t2, t3 in calcs: 244 print( 245 '%2d: Fade In: %s; Fade Out: %s; start: %s; stop: %s; Len: %s' 246 % (i, fin, fout, start, stop, tlen) 247 ) 248 track = FakeTrack(start, stop, tlen) 249 assert fader.calculate_fades(track, fin, fout) == (t0, t1, t2, t3) 250 i += 1 251