Making Music Boxes

Python 2, 95 94 bytes

-1 byte thanks to Value Ink

x=1
for i in input():
 if x:o=['.']*7
 if'@'<i:o[ord(i)-65]='O'
 if'*'>i:x=i>'('
 if x:print o

Try it online! or Try all test cases

Explanation

'@'<i is to check if i is a letter, replacing the . by O on the right position.
'*'>i is to check if i is a parenthesis, if it is x=i>'(' will put 0 on x to prevent the printing/clearing of o, when i==')', it will put 1 on x re-enabling the printing/clearing of o.
When i=='.' nothing will be changed, and '.......' will be printed.
The charater order is given by their ASCII code, where '('<')'<'*'<'.'<'@'<'A'


Batch, 209 bytes

@set s=%1
@set p=)
@for %%n in (a b c d e f g)do @set %%n=.
:g
@if %s:~,1% lss @ (set "p=%s:~,1%")else set %s:~,1%=O
@set s=%s:~1%
@if %p%==( goto g
@echo %a%%b%%c%%d%%e%%f%%g%
@if not "%s%"=="" %0 %s%

Works by accumulating letters and outputting the line if the last symbol seen was not a (.


Röda, 97 78 76 bytes

{search`\(\w+\)|.`|{|c|seq 65,71|{|l|["O"]if[chr(l)in c]else["."]}_;["
"]}_}

Try it online!

It's an anonymous function that reads the input from the stream. Use it like this: main { f={...}; push("ABCD") | f() }. It uses the regex from ETHproductions' answer.

Ungolfed:

{
    search(`\(\w+\)|.`) | for chord do
        seq(ord("A"), ord("G")) | for note do
            if [ chr(note) in chord ] do
                push("O")
            else
                push(".")
            done
        done
        push("\n")
    done
}

Previous answer:

f s{(s/"(?=([^()]*(\\([^()]*\\))?)*$)")|{|c|seq 65,71|{|l|["O"]if[chr(l)in c]else["."]}_;["
"]}_}

Try it online!

It works by splitting the given string at places where the string following contains only matched parentheses. Then, for each chord, it iterates through possible notes and print O if the note is a member of the chord and . otherwise.