Storing Audio Volumes

Post your questions and help other users.

Moderator: Martin

Post Reply
User avatar
digitalstone
Posts: 342
Joined: 21 Oct 2017 12:36
Location: The Netherlands

Storing Audio Volumes

Post by digitalstone » 03 Feb 2018 20:06

I want to use a global map-variable to store all of my volumes in with the "Set Audio Volume" block.

But when i place the variables into that block, instead of changing that values, it just creates an extra global variable with the name i said to store it to.
Tried it with/without quotes and all the other ways.
Just don't get it to work.
Phone: LG Nexus 5X (rooted vanilla Android 7.1.2)

User avatar
Desmanto
Posts: 2709
Joined: 21 Jul 2017 17:50

Re: Storing Audio Volumes

Post by Desmanto » 04 Feb 2018 12:25

Strange, I also have the same result. Don't know if it is limitation or a bug. Recently, I have been using the glovar lavishly (well, it won't run out anyway :)). Can't imagine if I don't use map/list, probably I would have hundreds to thousands glovar. So far, I don't put the glovar directly at the Store/Restore Audio Volume. In most of the flows which need glovar map, I would use intermediate variable and later assign it to the map. So here is the method I would use.

WARNING!!! : Prepare yourself for a wall text!!!

1. Storing via direct assignment
I would use the Store Audio Volumes as example here. But basically you can use to store any kind of variables, especially the one which has some kind of state or values just like the volumes.

For the first time, you don't have glovar yet. You can use script to create it if not exist yet. But since it is a one-time job, I will just create it manually in the glovar menu (rather than wasting a single line code that never executed anymore), add global_volume, type Map. No need to add any value, just press OK. So we create a blank global_volume with the type Map, ready to be assigned with value.

Store
For Store Audio Volumes, assign all volume needed to local variables. Example as this.
1. Store Audio Volumes local variable.png
1. Store Audio Volumes local variable.png (70.52 KiB) Viewed 23372 times
After that, you will have collection of intermediate values. Add Script action after it to assign it to the glovar. It is a simple boring assignment.

Code: Select all

global_volume["alarm"] = alarm;
global_volume["dtmf"] = dtmf;
global_volume["music"] = music;
global_volume["notification"] = notification;
global_volume["ring"] = ring;
global_volume["system"] = system;
global_volume["voice_call"] = voice_call;
global_volume["ringer_mode"] = ringer_mode;
global_volume["interruptions_mode"] = interruptions_mode;
Now the global_volume will be populated with all the value from the volume, mapped each to its correct variable.

Restore
To retrieve the value later in another flow/execution, you can't just use the global_volume["alarm"] for the same reason. So you have to assign the glovar to intermediate value again. Add Script first and reverse the value assignment (another boring one).

Code: Select all

alarm = global_volume["alarm"];
dtmf = global_volume["dtmf"];
music = global_volume["music"];
notification = global_volume["notification"];
ring = global_volume["ring"];
system = global_volume["system"];
voice_call = global_volume["voice_call"];
ringer_mode = global_volume["ringer_mode"];
interruptions_mode = global_volume["interruptions_mode"];
Then use the value newly created to the Action Restore Audio Volumes, use variables alarm, dtmf etc, similar to the Store Audio Volumes.

This is the most basic method, easy to understand, easy to debug, since you can see the value assignment clearly.
Use this method at the beginning, or when you have key less than 5.

2. Using loop for all keys
As you have more and more key-value in the map, the lines of script for assigning the value keeps getting longer. It started to become annoying. As every addition/removal of key-value pair, you should add/remove it twice, at the storing script and at the restoring script. It can be missed if the flow utilizing it is in different flow or not quite related to each other. (example : you add in the storing script, but forgot to add in the restoring script).

Store
So, we need a way to dynamically assign all value from the map, no matter if we add or remove some key-value from the map. Here comes the loop upon the keys in the map. We can use getMapKeys() to get all Keys from the glovar map and loop assigning value to it.

Code: Select all

for(i in getMapKeys(global_volume))
  global_volume[i] = getValue(i, 0);
Here, we can't just use

Code: Select all

global_volume[i] = i;
[/color] since it will then assign the value only. For first loop, i = "alarm", so it is just like evaluating
global_volume["alarm"] = "alarm"; //which is wrong.
We must use getValue(i, 0); as i = "alarm", it will be evaluated as, getValue("alarm", 0); which will then evaluated to the volume of alarm (example : 10). The end evaluation is like this
global_volume["alarm"] = alarm; //the correct one, as alarm is 10
Looping all of them will store the corresponding key-value assignment. The 0 just to fulfill the requirement for default value. This getValue() is part of the dynamic value assignment, you can check more at the index, creating dynamic variables.

Restore
The restore part is similar, simply reverse the value assignment, and use setValue() instead.

Code: Select all

for(i in getMapKeys(global_volume))
  setValue(i, global_volume[i]);
Same concept here, you can't just use

Code: Select all

i = global_volume[i]
; for first loop, i = "alarm", so it is just like evaluating
i = global_volume["alarm"]; // i = 10, not creating new variable alarm = 10
By using setvalue(), i will be evaluated first to "alarm". So the end it is just like
alarm = global_volume["alarm"]; //the correct one, {alarm} will be created
Looping all of them will create variables from all of the keys in the global_volume.

The catch for this method is you must have the key already. So global_volume must already have the alarm, dtmf, music,, etc key inside; so they will appear when using getMapKeys().
2. global_volume.png
2. global_volume.png (42.68 KiB) Viewed 23372 times
You can use the first method to create it, or you can simply add the key directly in Glovar menu, add all the keys you need and leave the value blank. I usually just create it manually, since it is again the same one-time job.

Use this method when :
- you have to dynamically add/remove key-value pair, so you don't need to think about changing the code everytime you add/remove the variable.
- all values from the glovar only be used/modified in that flow only.
- you have more than 5 key-value pairs.
Since you can see that 5 key-value requires 5 lines of script in both store/restore; while using loop for(), you only need 2 lines of script. For less than 5 key-value, just use the first method. Sometimes it is better to be less optimized a bit, for the sake of readability. It is easier to read and understand the code in first method, than the for() loop.


3. Loop only certain keys
As you advance, now you utilize the map not only for single flow, but also for another flows. In certain flow, you only need to use 4 values from the global_volume (example : alarm, dtmf, music, notification). Using the method 2, it will store/restore all values in the key list. Depends on the flow, it may cause error; or worse, a logic flaw : wrong value assignment but no error given (which is more disastrous).

Store
So to only use certain keys, we should create another list to store the keys we need. Then instead of looping using getMapKeys(), we loop using this list. Adding a newList() and remember to assign the value exactly as the key as the global_volume

Code: Select all

voluse = newList("alarm", "dtmf", "music", "notification");
for(i in voluse)
  global_volume[i] = getValue(i, 0);
The concept is the same as method 2, but we limit only storing the keys from voluse.

Restore
Reversing the method, we also use the same newList() for restore.

Code: Select all

voluse = newList("alarm", "dtmf", "music", "notification");
for(i in voluse)
  setValue(i, global_volume[i]);
The catch are you have to type the keys exactly as the keys in the map (sometimes can type wrong) and when adding new keys to include in the loop, you have to add in both store/restore. You can mitigate this by storing the list in another variable, but I think that is not necessary, as if you have reach this stage, usually we don't change the key so frequently (unless you do).

Use this when you have only certain keys needed in certain flow. Probably you have a glovar Map consist of 15 keys and used in 3 separate flows. You can assign the needed keys in each flow using the voluse.


4. Loop all keys except certain keys
Reversing the idea from method 3, now we need to loop all keys, but only maybe 1 or 2 keys to be excluded. You want all future added/removed keys to be updated just like in method 2, but you also want to exclude certain keys just like in method 3. Example, for this store volume, you want to use all values those has volume, except ringer_mode and interruptions_mode. So you want to exclude only these 2 keys.

Store
To do this, from method 3, we should create another newList() to store the excluded keys.

Code: Select all

volrem = newList("ringer_mode", "interruptions_mode");
voluse = removeAllElementValues(getMapKeys(global_volume), volrem);
for(i in voluse)
  global_volume[i] = getValue(i, 0);
The concept derived from method 3, but we reverse the idea. volrem is used to exclude the keys. We use getMapKeys() to get all keys from global_volume, then remove all of the value which are listed in volrem. The result is voluse now contains all keys from global_volume, exclude the ones from volrem. The we loop the voluse as usual. Any new added/removed key-value will be always included.

Restore
Reversing the method, we also use the same newList for restore.

Code: Select all

volrem = newList("ringer_mode", "interruptions_mode");
voluse = removeAllElementValues(getMapKeys(global_volume), volrem);
for(i in voluse)
  setValue(i, global_volume[i]);
The catch are the same as method 3; type the key exactly and add new exclusion in both store/restore.

Use this when you want to include all keys, except the excluded ones. Probably you have 2 keys to store certain state and time; all other keys added and removed dynamically depends on the need. Change the volrem to your need.

Test Flow
I purposely created the flow to illustrate the concept above (need automagic 1.34, as I have notes inside) : flow_Store_Volume_Global_20180204_000000.xml
3. Store Volume Global test flow.png
3. Store Volume Global test flow.png (105.17 KiB) Viewed 23372 times
The flow is far from optimized, it has so many duplicated element. I can optimize it, put a input dialog for selection, or combine the script. But that will defeat the purpose of the test flow (so spare me :D). I intentionally separate all four methods and add debug dialog so you can check the value directly.

To test the flow, simply connect the trigger to the branch you want to test. Remember to create the global_volume as type Map first in the glovar menu. To test the first method, simply connect the trigger to the left most Store Audio Volume. Check the debug dialog result (global_volume). Try to change some of your volume slider (alarm, music etc). Then delete the connection, connect now to the script next to it. Check your volume slider, now it has been returned to the state when storing it. You can also see a lot of variable created from the global_volume.

This is just a test flow for the concept above. You can modify the flow or just utilize the concept in you other flow. There is another way of using the map value to store/restore value, which I use for logging trigger events. But the concept is much wider, and I haven't finish the complement flow to use the value. Maybe I will share in another occassion, after I have finished it.
Last edited by Desmanto on 15 Apr 2018 11:50, edited 1 time in total.
Index of Automagic useful thread List of my other useful posts (and others')
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.

User avatar
digitalstone
Posts: 342
Joined: 21 Oct 2017 12:36
Location: The Netherlands

Re: Storing Audio Volumes

Post by digitalstone » 04 Feb 2018 14:01

1. Thanks again Desmanto
2. Damned Desmanto :lol:

I already thought of your first method because that's the most obvious (and don't have a gazillion glovars running about).
But i take it you're using this for the Index of useful thread.

Followup question though:
Do you experience any side-effects from having that many glovars such as battery-drain?
I can imagine the buttload of triggers in your flows as well that will constantly go off etc.
Phone: LG Nexus 5X (rooted vanilla Android 7.1.2)

User avatar
Desmanto
Posts: 2709
Joined: 21 Jul 2017 17:50

Re: Storing Audio Volumes

Post by Desmanto » 04 Feb 2018 17:49

Yeah, of course for my own documentation. :D I believe if I can explain it step by step clearly in a structured format, I have fully understand it myself. So far, before above post, if I have to use the map store/restore, I still have to look again at my finished flow to copy the concept. Now I confidently say I have remembered it and can type the script without looking anymore. (or at least i can visit this again to refresh the concept again).

I actually just wanna reply a bit, but can't stop typing. :) Since it is Sunday, and I have spare time to slowly put in the idea. Your use case is a very perfect example of using the map, so can't help to document it at once. I can't sleep tonight if I don't finish it :lol:

I used a lot of glovar, but most of them are not the trigger (you can't trigger using glovar map/list). It is mostly for logging and saving state, example to log incoming sms/whatsapp chatting. Sometimes the flow is running, and I forgot to turn it off. Probably someone interrupt me (either chatting or direct contact) and I switch to other app and forgot it completely. Later I find out a big drain and just remembered that I use the logging flow. Check the values, I have thousand of list element already. :o The effect can be seen also in other flow, when calling for other glovar, it is slower than when I don't have that thousand list. (so it is noticeable when you have gazillion of multinested list/map). I usually just convert it to json and offload it to text file. If I need it again, simply init the text file again.

But if no logging running, the battery of course still drain more compared to when I am not using glovar map/list as intense as now. But don't know if it is the phone battery (already 1,5 years) or automagic. Since if I use it all day to create flow, I can still achieve almost the same SOT as 1,5 years ago. (7-8 hours). So can't be sure whether it has big impact to battery life. I don't usually use my phone below 50%, so I will try to check later for several days ahead. Maybe I will try to create a flow to log it.
Index of Automagic useful thread List of my other useful posts (and others')
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.

User avatar
Desmanto
Posts: 2709
Joined: 21 Jul 2017 17:50

Re: Storing Audio Volumes

Post by Desmanto » 05 Feb 2018 17:00

Today I just tested it out, not much changes in the flow state, probably only disable one logging flow. From 100% - 3%, I got about 8 hours usage (starting from unplugged to 3%), with 5 hours 22 minutes SOT. But Chrome has CPU total of 1 hour 51 minutes, so maybe chrome is the culprit. I notice chrome started to drain so much power since maybe v55 above, need to troubleshoot this. If I don't use chrome at all (when at home, i just browse at my PC, not at phone anymore), probably the whole Chrome CPU usage can be added as the SOT, resulting in 7+ hours, which is quite close to what i experience if I use it only to create flow for the whole day. Automagic never appear on top 5 battery usage, but sometimes appear at top 10. So yeah, I can roughly say the glovar didn't affect much. The drain hasn't changed much since I started to use glovar map/list heavily. I have approx 40 active flows with probably 100+ triggers (half of the flow has multiple triggers).
Index of Automagic useful thread List of my other useful posts (and others')
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.

User avatar
digitalstone
Posts: 342
Joined: 21 Oct 2017 12:36
Location: The Netherlands

Re: Storing Audio Volumes

Post by digitalstone » 05 Feb 2018 17:21

Hehe you sound busy. I too had a thing with documenting and such once.
But the actual stuff became more important to me, so scripting/programming became more of a thing that i just did from time to time when necessary. I always figure it out eventually.
(it's called sloppy :? )

Automagic also never uses much with my phone, though it's doing stuff every minute. Very efficient yet powerful app.
I think i'm just going to build whatever i like and see what happens since i don't have a lot of time on my hands.
Phone: LG Nexus 5X (rooted vanilla Android 7.1.2)

Post Reply